📦 std::move vs std::forward: Когда и зачем?
На собеседованиях часто спрашивают про rvalue-ссылки, но в реальном коде мы постоянно путаемся: когда делать
Давайте разберем на жизненных примерах.
1.
Сценарий 1: Передача владения (
Это классика.
Сценарий 2: Оптимизация тяжелых объектов
У вас есть локальный вектор, который вы хотите сохранить в поле класса. Зачем его копировать?
2.
Представьте, что вы пишете функцию-обертку (wrapper). Она принимает аргумент и должна передать его дальше другой функции.
⚫️ Если ей передали временный объект (rvalue) - она должна передать его как rvalue (чтобы сработал move).
⚫️ Если передали обычную переменную (lvalue) - она должна передать как lvalue (копия).
Сценарий: Фабрики и Обертки
⚡️ Шпаргалка
1.
2.
#cpp #cpp11 #movesemantics #coding #interview #tips
➡️ @cpp_geek
На собеседованиях часто спрашивают про rvalue-ссылки, но в реальном коде мы постоянно путаемся: когда делать
move, а когда forward?Давайте разберем на жизненных примерах.
1.
std::move - "Это мое, но забирай!" 🚚std::move - это безусловное приведение к rvalue. Вы говорите компилятору: "Мне этот объект больше не нужен. Можешь выпотрошить его и забрать данные, не копируя их".Сценарий 1: Передача владения (
unique_ptr)Это классика.
std::unique_ptr нельзя скопировать, его можно только переместить.
auto ptr = std::make_unique<BigData>();
// process(ptr); // ❌ Ошибка компиляции! Копирование запрещено.
process(std::move(ptr)); // ✅ ОК. Владение передано, ptr теперь пуст.
Сценарий 2: Оптимизация тяжелых объектов
У вас есть локальный вектор, который вы хотите сохранить в поле класса. Зачем его копировать?
void SetData(std::vector<int> newData) {
// Мы крадем буфер памяти у newData.
// Копирования элементов НЕ происходит.
this->data_ = std::move(newData);
}
2.
std::forward - "Я просто посредник" 📮std::forward используется почти исключительно в шаблонах. Его цель - Perfect Forwarding (Идеальная передача).Представьте, что вы пишете функцию-обертку (wrapper). Она принимает аргумент и должна передать его дальше другой функции.
std::move здесь всё испортит (он всё превратит в rvalue). Тут нужен std::forward.Сценарий: Фабрики и Обертки
template <typename T>
void LogAndAdd(std::vector<T>& vec, T&& item) {
std::cout << "Adding item...";
// forward сохранит категорию значения item.
// Если item был временным — сработает push_back(T&&) (перемещение).
// Если item был переменной — сработает push_back(const T&) (копия).
vec.push_back(std::forward<T>(item));
}
⚡️ Шпаргалка
1.
std::move используем, когда мы знаем, что объект нам больше не нужен, и мы хотим отдать его ресурсы (обычный код).2.
std::forward используем, когда мы пишем шаблон, который принимает "универсальную ссылку" (T&&), и нам нужно пробросить аргумент дальше "как есть" (библиотечный код).#cpp #cpp11 #movesemantics #coding #interview #tips
➡️ @cpp_geek
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3