🧠 Задача с подвохом для продвинутых C++ разработчиков
🔹 Уровень: Advanced
🔹 Темы:
📌 Условие
Рассмотрим следующий код:
❓ Вопросы
1. Что будет выведено на экран?
2. Почему
3. Что изменится, если заменить
🔍 Разбор
✅ Ожидаемый вывод:
🔧 Почему так происходит
-
-
- Временный объект уничтожается (вызывается `Dtor`).
-
🔄 Если заменить `reserve(3)` на `resize(3)`
-
-
- Это может привести к копированию или перемещению уже созданных элементов.
⚠️ Подвох
Многие ошибочно считают, что
🧠 Вывод
-
-
- Не путай эти методы — от этого зависит и производительность, и семантика.
📌 Совет:
Если не хочешь лишнего перемещения, используй
🔹 Уровень: Advanced
🔹 Темы:
std::vector
, управление памятью, конструкторы/деструкторы, reserve()
vs resize()
📌 Условие
Рассмотрим следующий код:
#include <iostream>
#include <vector>
struct Foo {
Foo() { std::cout << "Ctor\n"; }
~Foo() { std::cout << "Dtor\n"; }
Foo(const Foo&) { std::cout << "Copy\n"; }
Foo(Foo&&) noexcept { std::cout << "Move\n"; }
};
int main() {
std::vector<Foo> v;
v.reserve(3); // Резервируем место под 3 элемента
std::cout << "--- Pushing ---\n";
for (int i = 0; i < 3; ++i) {
v.push_back(Foo());
}
std::cout << "--- Done ---\n";
}
❓ Вопросы
1. Что будет выведено на экран?
2. Почему
reserve()
не предотвращает конструкторы копирования/перемещения? 3. Что изменится, если заменить
reserve(3)
на resize(3)
?🔍 Разбор
✅ Ожидаемый вывод:
--- Pushing ---
Ctor
Move
Dtor
Ctor
Move
Dtor
Ctor
Move
Dtor
--- Done ---
Dtor
Dtor
Dtor
🔧 Почему так происходит
-
Foo()
создаёт временный объект. -
push_back()
вызывает перемещающий конструктор Move
. - Временный объект уничтожается (вызывается `Dtor`).
-
reserve(3)
выделяет память, но не создаёт объектов.🔄 Если заменить `reserve(3)` на `resize(3)`
-
resize(3)
создаст 3 объекта Foo через конструктор по умолчанию. -
push_back(Foo())
добавит четвёртый, возможно вызовет realocation. - Это может привести к копированию или перемещению уже созданных элементов.
⚠️ Подвох
Многие ошибочно считают, что
reserve(n)
создаёт n
объектов. Но это не так — reserve()
только выделяет память, не вызывая конструкторы. Именно поэтому внутри push_back
всё равно происходит перемещение или копирование.🧠 Вывод
-
reserve()
— экономия на реаллокациях, без создания объектов. -
resize()
— создаёт n
объектов, вызывает конструкторы. - Не путай эти методы — от этого зависит и производительность, и семантика.
// Резервирует память, не создаёт объекты
v.reserve(10);
// Создаёт 10 объектов Foo
v.resize(10);
📌 Совет:
Если не хочешь лишнего перемещения, используй
emplace_back()
:
v.emplace_back(); // Вызывает конструктор Foo напрямую внутри вектора