C++ geek
3.73K subscribers
276 photos
4 videos
25 links
Учим C/C++ на примерах
Download Telegram
📦 std::move vs std::forward: Когда и зачем?

На собеседованиях часто спрашивают про 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). Она принимает аргумент и должна передать его дальше другой функции.

⚫️Если ей передали временный объект (rvalue) - она должна передать его как rvalue (чтобы сработал move).
⚫️Если передали обычную переменную (lvalue) - она должна передать как lvalue (копия).

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
👍83