Я видел это здесь: Move Constructor вызывает базовый класс Move Constructor
Может ли кто-нибудь объяснить:
- разница между
std::move
иstd::forward
, желательно с некоторыми примерами кода? - Как легко об этом думать, и когда использовать какой
c++
c++11
perfect-forwarding
aCuria
источник
источник
move
когда хотите переместить значение иforward
когда вы хотите использовать идеальную пересылку. Это не ракетостроение здесь;)Ответы:
std::move
берет объект и позволяет рассматривать его как временное (значение). Хотя это и не семантическое требование, обычно функция, принимающая ссылку на rvalue, делает ее недействительной. Когда вы видитеstd::move
, это означает, что значение объекта не должно использоваться впоследствии, но вы все равно можете назначить новое значение и продолжить его использование.std::forward
имеет один вариант использования: для приведения параметра функции-шаблона (внутри функции) к категории значений (lvalue или rvalue) вызывающая сторона использовала его для передачи. Это позволяет передавать аргументы rvalue как значения rvalue, а lvalues - как lvalues - схему, называемую «идеальная пересылка».Для иллюстрации :
Как упоминает Говард, есть также сходства, поскольку обе эти функции просто приводятся к ссылочному типу. Но помимо этих конкретных случаев использования (которые охватывают 99,9% полезности приведенных ссылок на rvalue), вы должны использовать
static_cast
напрямую и написать хорошее объяснение того, что вы делаете.источник
std::forward
«S только случай использования является совершенным экспедиторская аргументов функции. Я сталкивался с ситуациями, когда я хочу полностью пересылать другие вещи, такие как члены объекта.Оба
std::forward
иstd::move
ничто иное как слепки.Выше приведено выражение lvalue
x
типа X к выражению rvalue типа X (точнее, xvalue).move
также можно принять значение:и в этом случае это функция тождества: принимает r-значение типа X и возвращает r-значение типа X.
С помощью
std::forward
вы можете выбрать пункт назначения в некоторой степени:Приводит выражение lvalue
x
типа X к выражению типа Y. Существуют ограничения на то, что может быть Y.Y может быть доступной Базой X, или ссылкой на Базу X. Y может быть X, или ссылкой на X. Нельзя отбрасывать cv-квалификаторы с помощью
forward
, но можно добавлять cv-квалификаторы. Y не может быть типом, который просто конвертируется из X, кроме как через доступное базовое преобразование.Если Y является ссылкой lvalue, результатом будет выражение lvalue. Если Y не является ссылкой lvalue, результатом будет выражение rvalue (точнее xvalue).
forward
может принимать аргумент rvalue, только если Y не является ссылкой lvalue. То есть вы не можете привести значение к значению lvalue. Это по соображениям безопасности, так как это обычно приводит к висящим ссылкам. Но приведение rvalue к rvalue - это нормально и разрешено.Если вы попытаетесь указать Y для чего-то, что не разрешено, ошибка будет обнаружена во время компиляции, а не во время выполнения.
источник
std::forward
, то после выполнения этой функции смогу ли я использовать этот объект? Я знаю, что, в случаеstd::move
, это неопределенное поведение.move
: stackoverflow.com/a/7028318/576911 Посколькуforward
, если вы передаете lvalue, ваш API должен реагировать так, как будто он получает lvalue. Обычно это означает, что значение будет неизменным. Но если это неконстантное значение, ваш API, возможно, изменил его. Если вы передаете значение r, это обычно означает, что ваш API, возможно, переместился с него, и, таким образом, будет применяться stackoverflow.com/a/7028318/576911 .std::forward
используется для пересылки параметра , точно так , как он был передан в функцию. Как показано здесь:Когда использовать std :: forward для пересылки аргументов?
Использование
std::move
предлагает объект в качестве rvalue, чтобы, возможно, соответствовать конструктору перемещения или функции, принимающей rvalue. Это делает это,std::move(x)
даже еслиx
само по себе не является значением.источник