забрать владение
std::move — просто static_cast к &&
void foo(Type&& object) — у object можно забрать владение, и хоть это RVALUE ссылка, сам объект LVALUE (простое правило: всё имеет имя — lvalue). Если владение передаётся где-то в другой функции, которая вызывается из foo, надл сделать std::move(object)
После выполнения перемещения (не просто std::move, а вызвали конструктор/оператор= перемещения) объект, из которого мувнули находится в unspecified состоянии, на котором можно вызывать деструктор и операции, которые не требуют preconditions. Это относится к стд классам, но обычно и остальные библиотеко-писатели делают аналогично.
Использование такого объекта не даёт ошибку компиляции как в Расте. Хотя скорее всего статанализатор ругнётся.
Теперь про более сложную часть
template <typename T>
void foo(T&& o);
T&& — это не rvalue reference, а forwarding. Forwarding reference может принимать как rvalue, так и lvalue ссылки.
Правило такое: если пришла lvalue ссылка, то o будет иметь тип [const] T&, а если rvalue ссылка или временный объект — то просто T
А что если мы захотим передать этот объект куда-то. Причем если там пришёл объект из которого можно мувнуть — мы хотим мувнуть? (то бишь пришла не lvalue ссылка)
std::move здесь не подойдёт, потому что он превратит всё к && — даже то, что мы не хотим
Поэтому используется std::forward, который мувает только если изначальный объект был rvalue ссылкой, иначе просто передаёт lvalue ссылку.
Надеюсь, что-то было понятно.
За подробностями к Майерсу или Джоссатису.
Майерс forwarding reference называет "универсальной ссылкой"
Всё классно, только ВЛАДЕНИЕ тут причём?
Я был бы аккуратнее с фразой >> std::move — просто static_cast к && потому что на самом деле, так выглядит форвард (при касте происходит сжатие ссылок), а не мув (который предвариательно требует стереть ссылку с типа, чтобы при добавлении && не произошло сжатие)
Обсуждают сегодня