9Miten `std::vector` hallitsee kapasiteettia, kasvamista, muistin uudelleenvarointia ja iteraattorien stabiiliutta?
`std::vector` tallentaa alkiot peräkkäin muistiin ja seuraa sekä kokoa (size) että kapasiteettia (capacity). Koko on luotujen alkioiden määrä; kapasiteetti on varatun muistin määrä, johon voidaan tallentaa alkioita ennen kuin uusi muistinvaraus on tarpeen. Kun alkioiden lisääminen ylittäisi kapasiteetin, `vector` varaa suuremman muistilohkon – yleensä käyttäen toteutuskohtaista geometristä kasvustrategiaa – siirtää tai kopioi olemassa olevat alkiot, tuhoaa vanhat ja vapauttaa vanhan muistin. `reserve(n)` kasvattaa kapasiteettia muuttamatta kokoa, kun taas `resize(n)` muuttaa kokoa luomalla tai tuhoamalla alkioita. Muistin uudelleenvaraus mitätöi kaikki alkioihin osoittavat iteraattorit, viittaukset ja osoittimet; jopa ilman muistin uudelleenvarausta operaatiot, kuten `insert` ja `erase`, voivat mitätöidä muutoskohdassa tai sen jälkeen sijaitsevat positiot.
Kokeile vastata tähän kysymykseen tekoälyvalmentajan kanssa
10Mitä mitätöitymissääntöjä tulisi tietää peräkkäisrakenteisten ja solmupohjaisten standardisäiliöiden osalta?
Mitätöitymissäännöt riippuvat säiliöstä ja operaatiosta. Peräkkäisrakenteisilla säiliöillä, kuten vector ja string, iteraattoreiden ja viitteiden pysyvyys on herkkä: kasvu voi aiheuttaa muistin uudelleenvarauksen ja mitätöidä kaikki iteraattorit, viitteet ja osoittimet. Lisäksi alkioiden lisääminen tai poistaminen voi siirtää alkioita ja mitätöidä muutoskohdan ja sitä seuraavat sijainnit, vaikka muistia ei varattaisi uudelleen. Solmupohjaiset järjestetyt säiliöt, kuten list, map, set ja niiden multi-versiot, pitävät olemassa olevien, poistamattomien alkioiden iteraattorit ja viitteet yleensä voimassa lisäyksien yli; alkion poistaminen mitätöi kyseiseen poistettuun alkioon osoittavan iteraattorin tai viitteen. Myös järjestämättömät säiliöt tallentavat alkionsa solmuihin, joten viitteet ja osoittimet alkioihin pysyvät yleensä voimassa uudelleenhajautuksen (rehash) aikana, mutta uudelleenhajautus mitätöi iteraattorit. deque-säiliöllä on omat segmentoitua tallennustilaa koskevat erityissääntönsä. Käytännössä tarkista aina tietty säiliö ja operaatio ennen kuin tallennat iteraattoreita tai viitteitä muutosten yli.
Kokeile vastata tähän kysymykseen tekoälyvalmentajan kanssa
11Vertaile `std::map`-, `std::unordered_map`- ja flat-map-tyyppisiä säiliöitä taustajärjestelmien hakutauluina.
`std::map` on järjestetty, yleensä puurakenteeseen perustuva assosiatiivinen säiliö, jolla on logaritminen haku-, lisäys- ja poistoaika; se on hyödyllinen, kun lajiteltu läpikäynti, välikyselyt tai järjestystakuut ovat tärkeitä. `std::unordered_map` perustuu hajautustauluun ja tarjoaa keskimäärin vakioaikaiset tarkan avaimen operaatiot ilman avainten järjestystä; se on usein hyvä oletusvalinta suuriin muuttuviin hakutauluihin, kun hajautus toimii hyvin. Flat-map-tyyppinen säiliö tallentaa lajitellut avain-arvoparit peräkkäin muistiin, mikä tarjoaa hyvän välimuistipaikallisuuden ja nopean läpikäynnin tai puolitushaun, mutta lisäys ja poisto rakenteen keskeltä ovat lineaarisia operaatioita. Taustajärjestelmien hakutaulujen valinta tulisi tehdä sen perusteella, vaatiiko työkuorma järjestystä tai välikyselyitä, pääasiassa tarkkoja hakuja, usein tapahtuvaa muokkausta, ennustettavaa latenssia, muistin lisäkuormaa ja välimuistin toimintaa.
Kokeile vastata tähän kysymykseen tekoälyvalmentajan kanssa
12Selitä `std::optional` ja tyypilliset taustajärjestelmien käyttötapaukset puuttuvien arvojen esittämiseen.
`std::optional<T>` edustaa joko sen sisältämää `T`-arvoa tai arvon puuttumista. Tyhjää tilaa edustaa `std::nullopt`. Koodissa voidaan tarkistaa `has_value()` tai käyttää optionalia totuusarvoyhteydessä, päästä arvoon käsiksi `*`-operaattorilla tai `value()`-metodilla, ja antaa oletusarvo `value_or()`-metodilla. Taustajärjestelmäkoodissa se on hyödyllinen tietokannan kentille, jotka voivat olla tyhjiä (nullable), valinnaisille pyyntö- tai konfiguraatiokentille, välimuistin tai tietovaraston hudeille, joissa arvon puuttumista odotetaan, ja toimialueen tiloille, joissa -1:n tai tyhjän merkkijonon kaltainen erikoisarvo olisi moniselitteinen. Se mallintaa arvon puuttumista, ei polymorfismia tai rikasta virhetietoa.
Kokeile vastata tähän kysymykseen tekoälyvalmentajan kanssa
13Mitä ovat `std::string_view` ja `std::span`, ja millaisia elinkaareen liittyviä riskejä omistamattomat näkymät (non-owning views) tuovat mukanaan?
`std::string_view` on omistamaton näkymä yhtenäiseen merkkisarjaan; `std::span<T>` on omistamaton näkymä yhtenäiseen `T`-alkioiden sarjaan. Ne ovat hyödyllisiä nollakopioinnin (zero-copy) parametreille ja puskurien API-rajapinnoille, koska ne pitävät sisällään osoittimen ja pituuden varaamatta tai omistamatta muistia. Suurin riski liittyy elinkaareen: viitatun tallennustilan on oltava olemassa kauemmin kuin näkymän, eikä sitä saa mitätöidä näkymän käytön aikana. Näkymän palauttaminen tai tallentaminen viittaamaan väliaikaiseen objektiin, paikalliseen objektiin, tuhottuun objektiin tai uudelleenvarattuun säiliöön voi jättää jälkeensä roikkuvan näkymän (dangling view).
Kokeile vastata tähän kysymykseen tekoälyvalmentajan kanssa