9Як std::vector керує місткістю, збільшенням розміру, перерозподілом пам'яті та стабільністю ітераторів?
std::vector зберігає елементи неперервно і відстежує як розмір (size), так і місткість (capacity). Розмір — це кількість сконструйованих елементів; місткість — це обсяг виділеної пам'яті для елементів, доступний до того, як знадобиться наступне виділення. Коли додавання елементів перевищує місткість, вектор виділяє більший блок пам'яті (зазвичай використовуючи стратегію геометричного зростання, яка визначається реалізацією), переміщує або копіює наявні елементи, знищує старі та звільняє стару пам'ять. Виклик reserve(n) збільшує місткість без зміни розміру, тоді як resize(n) змінює розмір, створюючи або знищуючи елементи. Перерозподіл пам'яті (reallocation) робить недійсними всі ітератори, посилання та вказівники на елементи; навіть без перерозподілу пам'яті такі операції, як insert та erase, можуть зробити недійсними позиції на місці модифікації або після нього.
Відповісти на це запитання з ШІ-тренером
10Які правила інвалідації ви повинні знати для неперервних (contiguous) та вузлових (node-based) стандартних контейнерів?
Правила інвалідації залежать від контейнера та операції. Неперервні контейнери, такі як `vector` та `string`, мають низьку стабільність ітераторів та посилань: розширення може спричинити перерозподіл пам'яті (reallocation) та зробити недійсними всі ітератори, посилання та вказівники. Крім того, вставка чи видалення (`insert`/`erase`) може зсунути елементи та інвалідувати позиції у місці зміни та після неї навіть без перерозподілу пам'яті. Вузлові впорядковані контейнери, такі як `list`, `map`, `set` та їхні `multi`-варіанти, як правило, зберігають ітератори та посилання на існуючі не видалені елементи стабільними під час вставки; видалення елемента інвалідує ітератор або посилання лише на цей видалений елемент. Невпорядковані контейнери (unordered containers) також зберігають елементи у вузлах, тому посилання та вказівники на елементи зазвичай залишаються стабільними під час повторного хешування (rehash), але повторне хешування інвалідує ітератори. Контейнер `deque` має особливі правила сегментованого зберігання. На практиці завжди перевіряйте документацію до конкретного контейнера та операції, перш ніж зберігати ітератори або посилання між модифікаціями.
Відповісти на це запитання з ШІ-тренером
11Порівняйте std::map, std::unordered_map та контейнери в стилі flat-map для таблиць пошуку в бекенді.
`std::map` — це впорядкований асоціативний контейнер, зазвичай на основі дерева, з логарифмічним часом виконання операцій пошуку, вставки та видалення; він корисний, коли важливі відсортована ітерація, запити за діапазоном (range queries) або гарантії збереження порядку. `std::unordered_map` базується на хеш-таблиці з усередненим константним часом операцій за точним ключем і без впорядкування ключів; він часто є хорошим вибором за замовчуванням для великих змінюваних таблиць пошуку за умови якісного хешування. Контейнер у стилі flat-map зберігає відсортовані пари ключ-значення у безперервній області пам'яті, що забезпечує хорошу локальність кешу та швидку ітерацію і пошук (через бінарний пошук), але операції вставки та видалення посередині виконуються за лінійний час. Для бекенд-таблиць пошуку вибір залежить від того, чи потрібні робочому навантаженню впорядкування та діапазони, чи переважають пошуки за точним збігом, а також від частоти змін, передбачуваності затримки (latency), накладних витрат пам'яті та поведінки кешу.
Відповісти на це запитання з ШІ-тренером
12Поясніть призначення `std::optional` та типові варіанти використання в бекенді для представлення відсутніх значень.
`std::optional<T>` представляє або вміщене значення типу `T`, або відсутність значення. Порожній стан представлений через `std::nullopt`; код може перевірити `has_value()` або використати `optional` у булевому контексті, отримати доступ до значення за допомогою `*` або `value()`, а також надати значення за замовчуванням за допомогою `value_or()`. У серверному коді це корисно для полів бази даних, які можуть мати значення null, необов'язкових полів запитів/конфігурації, промахів кешу або репозиторію, де відсутність є очікуваною, а також станів предметної області, де маркерне значення (sentinel value), наприклад -1 або порожній рядок, було б неоднозначним. Він моделює відсутність значення, а не поліморфізм чи розширену інформацію про помилку.
Відповісти на це запитання з ШІ-тренером
13Що таке std::string_view та std::span, і які ризики щодо часу життя об'єктів створюють неволодіючі представлення?
std::string_view — це неволодіюче представлення безперервної послідовності символів; std::span<T> — це неволодіюче представлення безперервної послідовності елементів типу T. Вони корисні для параметрів із нульовим копіюванням (zero-copy) та буферних API (Application Programming Interface), оскільки містять вказівник і довжину, не виділяючи пам'яті та не володіючи нею. Основна небезпека пов'язана з часом життя: сховище даних, на яке є посилання, має жити довше, ніж представлення, і не повинно стати недійсним під час його використання. Повернення або збереження представлення на тимчасовий, локальний чи знищений об'єкт, а також на перерозподілений контейнер може призвести до появи посилання на недійсну пам'ять (dangling view).
Відповісти на це запитання з ШІ-тренером