Существует ли какая-либо разница между статическим приведением в значение rvalue и 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);

Ответы

Ответ 1

Да есть очень важная разница: std::move документы, что вы хотите сделать. Кроме того, бросок подвержен написанию ошибок, таких как забытый & или неправильный тип X.

Как видно, std::move еще меньше типа.

Ответ 2

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 до const A && или A &&?)
  • более подробно (я могу использовать поиск в текстовом редакторе, чтобы найти std:: move in project)
  • меньше ошибок, когда разработчик программного обеспечения пишет код

Ответ 3

Вы можете использовать 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