9Jak std::vector spravuje kapacitu, růst, realokaci a stabilitu iterátorů?
std::vector ukládá prvky souvisle (contiguously) a sleduje jak velikost (size), tak kapacitu (capacity). Velikost je počet zkonstruovaných prvků; kapacita je množství alokovaného úložiště pro prvky, které je k dispozici předtím, než je nutná další alokace. Pokud by přidání prvků překročilo kapacitu, vektor alokuje větší blok, obvykle s využitím geometrického růstu definovaného danou implementací, přesune nebo zkopíruje existující prvky, zničí ty staré a uvolní původní úložiště. reserve(n) zvyšuje kapacitu beze změny velikosti, zatímco resize(n) mění velikost konstrukcí nebo destrukcí prvků. Realokace zneplatní (invalidates) všechny iterátory, reference a ukazatele na prvky; dokonce i bez realokace mohou operace jako insert a erase zneplatnit pozice v místě modifikace nebo za ním.
Zkusit odpovědět na tuto otázku s trenérem AI
10Jaká pravidla zneplatnění (invalidation rules) byste měli znát u standardních kontejnerů se souvislou pamětí (contiguous) a těch založených na uzlech (node-based)?
Pravidla zneplatnění závisí na konkrétním kontejneru a operaci. Souvislé kontejnery, jako jsou `vector` a `string`, mají velmi křehkou stabilitu iterátorů a odkazů: růst jejich kapacity může vést k realokaci a zneplatnění všech iterátorů, odkazů i ukazatelů. Rovněž vkládání a mazání může posunout další prvky a zneplatnit tak pozice na místě změny nebo za ním i bez nutnosti realokace. Uspořádané kontejnery založené na uzlech, jako jsou `list`, `map`, `set` a jejich `multi` varianty, obecně udržují iterátory a odkazy na existující (nesmazané) prvky během vkládání stabilní; smazání prvku zneplatní iterátor či odkaz jen a pouze na daný smazaný prvek. Neuspořádané kontejnery (unordered containers) také ukládají prvky v uzlech, takže odkazy a ukazatele na prvky zůstávají při přehešování (rehash) povětšinou stabilní, avšak přehešování kompletně zneplatňuje iterátory. Kontejner `deque` má speciální pravidla spojená se segmentovaným úložištěm. V praxi si před ukládáním iterátorů nebo odkazů během jejich úprav (modifications) vždy ověřte daný kontejner a konkrétní operaci.
Zkusit odpovědět na tuto otázku s trenérem AI
11Porovnejte kontejnery `std::map`, `std::unordered_map` a kontejnery typu flat-map pro vyhledávací tabulky v backendu.
`std::map` je seřazený, obvykle na stromech založený asociativní kontejner s logaritmickou složitostí pro vyhledávání, vkládání a mazání; je užitečný, pokud záleží na seřazené iteraci, dotazech na rozsahy (range queries) nebo garanci zachování pořadí. `std::unordered_map` je kontejner založený na hashovací tabulce, s průměrně konstantní dobou pro operace nad přesným klíčem a bez zachování pořadí klíčů; často tvoří dobrou výchozí volbu pro velké, měnitelné vyhledávací tabulky za předpokladu dobré kvality hashování. Kontejner typu flat-map ukládá seřazené dvojice klíč/hodnota souvisle v paměti, což poskytuje dobrou lokálnost mezipaměti (cache locality), rychlou iteraci a vyhledávání pomocí binárního půlení, ovšem vkládání a mazání uprostřed paměťového bloku má lineární složitost. Pro vyhledávací tabulky na backendu byste měli volit podle toho, zda zátěž (workload) vyžaduje řazení či dotazy na rozsahy, převážně přesné vyhledávání, časté mutace, předvídatelnou latenci, nízkou paměťovou režii nebo zda závisí na chování mezipaměti (cache).
Zkusit odpovědět na tuto otázku s trenérem AI
12Vysvětlete `std::optional` a typické případy jeho použití v backendu pro reprezentaci chybějících hodnot.
Typ `std::optional<T>` reprezentuje buďto obsaženou hodnotu typu `T`, nebo žádnou hodnotu. Prázdný stav je reprezentován hodnotou `std::nullopt`; kód může zkontrolovat přítomnost hodnoty pomocí `has_value()` nebo použitím typu optional v booleovském kontextu, přistoupit k hodnotě pomocí operátoru `*` nebo metody `value()` a poskytnout výchozí hodnotu pomocí `value_or()`. V backendovém kódu je užitečný pro databázová pole s možností prázdné hodnoty (nullable), nepovinná pole v požadavcích nebo konfiguraci, nenalezení hodnoty (miss) v mezipaměti nebo repozitáři, kde se nepřítomnost očekává, a pro doménové stavy, u kterých by byla strážní hodnota (sentinel value) jako `-1` nebo prázdný řetězec nejednoznačná. Tento typ modeluje nepřítomnost hodnoty, nikoliv polymorfismus nebo detailní informace o chybách.
Zkusit odpovědět na tuto otázku s trenérem AI
13Co jsou `std::string_view` a `std::span` a jaká rizika týkající se životnosti objektů přinášejí nevlastnící pohledy (non-owning views)?
`std::string_view` je nevlastnící pohled (non-owning view) na souvislou posloupnost znaků; `std::span<T>` je nevlastnící pohled na souvislou posloupnost prvků typu `T`. Jsou užitečné pro parametry, které nevyžadují kopírování (zero-copy), a pro API vyrovnávacích pamětí, protože nesou ukazatel a délku bez alokace nebo vlastnictví paměti. Hlavním rizikem je životnost objektů: odkazované úložiště musí přežít (outlive) samotný pohled a nesmí být zneplatněno během používání pohledu. Vrácení nebo uložení pohledu na dočasný objekt, lokální objekt, zničený objekt nebo realokovaný kontejner může zanechat takzvaný visící pohled (dangling view).
Zkusit odpovědět na tuto otázku s trenérem AI