В чем разница между std :: move и std :: forward

Я видел это здесь: Move Constructor, вызывающий базовый class Move Constructor

Может ли кто-нибудь объяснить:

  1. разница между std::move и std::forward , желательно с некоторыми примерами кода?
  2. Как легко об этом думать, и когда использовать

3 Solutions collect form web for “В чем разница между std :: move и std :: forward”

std::move принимает объект и позволяет рассматривать его как временное (rvalue). Хотя это не семантическое требование, обычно функция, принимающая ссылку на rvalue, лишает ее права. Когда вы видите std::move , это означает, что значение объекта не должно использоваться впоследствии, но вы все равно можете присвоить новое значение и продолжить его использование.

std::forward имеет один прецедент: использовать шаблонный параметр функции (внутри функции) для категории значений (lvalue или rvalue), вызывающий, используемый для ее передачи. Это позволяет передавать аргументы rvalue как rvalues ​​и lvalues, которые должны передаваться как lvalues, схема, называемая «совершенная пересылка».

Чтобы проиллюстрировать :

 void overloaded( int const &arg ) { std::cout < < "by lvalue\n"; } void overloaded( int && arg ) { std::cout << "by rvalue\n"; } template< typename t > /* "t &&" with "t" being template param is special, and adjusts "t" to be (for example) "int &" or non-ref "int" so std::forward knows what to do. */ void forwarding( t && arg ) { std::cout < < "via std::forward: "; overloaded( std::forward< t >( arg ) ); std::cout < < "via std::move: "; overloaded( std::move( arg ) ); // conceptually this would invalidate arg std::cout << "by simple passing: "; overloaded( arg ); } int main() { std::cout << "initial caller passes rvalue:\n"; forwarding( 5 ); std::cout << "initial caller passes lvalue:\n"; int x = 5; forwarding( x ); } 

Как упоминает Говард, есть также сходства, так как обе эти функции просто передаются в ссылочный тип. Но вне этих конкретных случаев использования (которые покрывают 99,9% полезности ссылок на ссылки rvalue), вы должны использовать static_cast напрямую и написать хорошее объяснение того, что вы делаете.

Оба std::forward и std::move – это не что иное, как броски.

 X x; std::move(x); 

Вышеприведенное выражение lvalue x типа X относится к выражению rvalue типа X (точное значение x). move также может принимать значение rvalue:

 std::move(make_X()); 

и в этом случае это тождественная функция: принимает r-значение типа X и возвращает r-значение типа X.

С помощью std::forward вы можете в какой-то степени выбрать пункт назначения:

 X x; std::forward(x); 

Вставляет выражение lvalue x типа X в выражение типа Y. Существуют ограничения на то, что Y может быть.

Y может быть доступной базой X или ссылкой на базу X. Y может быть X или ссылкой на X. Нельзя отбрасывать cv-квалификаторы с помощью forward , но можно добавить cv-квалификаторы. Y не может быть типом, который просто конвертируется из X, за исключением использования доступного преобразования Base.

Если Y является ссылкой на lvalue, результатом будет выражение lvalue. Если Y не является ссылкой lvalue, результатом будет выражение rvalue (xvalue to exact).

forward может принимать аргумент rvalue только в том случае, если Y не является ссылкой lvalue. То есть вы не можете присвоить значение rvalue для lvalue. Это по соображениям безопасности, так как это обычно приводит к оборванным ссылкам. Но отличать rvalue до rvalue хорошо и разрешено.

Если вы попытаетесь указать Y на то, что не разрешено, ошибка будет обнаружена во время компиляции, а не во время выполнения.

std::forward используется для пересылки параметра точно так, как он передавался функции. Как показано здесь:

Когда использовать std :: forward для пересылки аргументов?

Использование std::move предлагает объект как rvalue, возможно, соответствует конструктору перемещения или функции, принимающей значения r. Он делает это для std::move(x) даже если x не является rvalue сам по себе.

Interesting Posts

Зачем мне «OR NULL» в MySQL при подсчете строк с условием

Как слушать клавиатуру в фоновом режиме и стрелять по нажатию клавиши по требованию?

Как глобально установить параметр preserveWhitespaces в Angular на false?

Скопировать весь сайт, включая PHP и SQL?

Смешивание файлов и циклов

Запуск файла bat с помощью планировщика Windows

Как преобразовать свойство в MongoDB из текста в дату?

Недопустимая форма Symfony2 без ошибок

Как отформатировать поле выбора фильтра даты для таблицы Excel Pivot

Использование различных типов SSD (не только SATA-based) в качестве системного диска

Нужно ли мне бить сердце, чтобы открыть TCP-соединение?

Могу ли я безопасно подключить только кабель питания USB-Y к другому источнику питания?

Как разместить RecyclerView внутри NestedScrollView?

Как конвертировать медиа с помощью VLC?

Преодоление беспроводных и проводных адаптеров моего ноутбука

Давайте будем гением компьютера.