Ответ 1
Да есть очень важная разница: std::move
документы, что вы хотите сделать. Кроме того, бросок подвержен написанию ошибок, таких как забытый &
или неправильный тип X
.
Как видно, std::move
еще меньше типа.
Описание для статического броска говорит
Если new_type является ссылочным типом rvalue, static_cast преобразует значение выражения в значение xvalue. Этот тип static_cast используется для реализации семантики перемещения в std:: move. (Поскольку С++ 11)
Означает ли это, что следующие эквиваленты?
(А)
X x1;
X x2 = static_cast<X&&>(x1);
(В)
X x1;
X x2 = std::move(x1);
Да есть очень важная разница: std::move
документы, что вы хотите сделать. Кроме того, бросок подвержен написанию ошибок, таких как забытый &
или неправильный тип X
.
Как видно, std::move
еще меньше типа.
T && В С++ 11 используется ссылка rValue. Они ведут себя как ссылка lvalue от С++ 98,03. Их цель - быть кандидатом на переезд. В С++ 98 такая конструкция может появляться при обрыве refrence
std:: move - превращает выражение в rvalue. Его можно было бы назвать rvalue_cast, но такого ключевого слова не существует.
Явный приведение к типу T && возможно в принципе. Реальный стандарт стоит немного денег, но в проекте ISO/IEC 14882: 2011 Существует такая информация
5.2.9 Статический литье
8)
Преобразования lvalue-to-rvalue (4.1), array-to-pointer (4.2) и function-to-pointer (4.3) применяются к Операнд....
С практической точки зрения удобнее использовать std:: move. Представьте себе такой пример:
#include <stdio.h>
#include <utility>
class A
{
public:
A () {printf ("A ()" "\n");}
A (const A &) {printf ("A (&)" "\n");}
A (A &&) {printf ("A (&&)" "\n");}
A (const A &&) {printf ("A (const &&)" "\n");}
~ A () {printf ("~ A ()" "\n");}
};
int main ()
{
const A obj;
A obj2 (std::move (obj)); // 1-st approach
A obj3 (static_cast <const A&&> (obj)); // 2-nd approach
}
Как для меня 1-й подход
Вы можете использовать static_cast<A &&>(a)
, когда a - значение r, но вы не должны использовать std::move(a)
.
Когда вы используете A && a = std::move(A())
, вы получаете свисающую ссылку.
Основная идея заключается в том, что время жизни временного не может быть дополнительно расширено "передачей": вторая ссылка, инициализированная ссылкой, на которую была связана временная связь, не влияет на ее время жизни.
std::move
реализация несколько похожа на
template <typename T>
constexpr decltype(auto) move(T && __t) noexcept // when used in std::move(A()),
// the lifetime of the temporary object is extended by __t
{
return static_cast<typename std::remove_reference<T>::type &&>(__t); // a xvalue returned, no lifetime extension
}
auto && a = std::move(A()); // the anonymous object wiil be destructed right after this line