简体   繁体   English

静态转换到右值引用和 std::move 之间有什么区别吗

[英]is there any difference between static cast to rvalue reference and std::move

The description for static cast says静态演员的描述说

If new_type is an rvalue reference type, static_cast converts the value of expression to xvalue.如果 new_type 是右值引用类型,则 static_cast 将表达式的值转换为 xvalue。 This type of static_cast is used to implement move semantics in std::move.(since C++11)这种类型的 static_cast 用于在 std::move 中实现移动语义。(C++11 起)

Does this confirm that the following are equivalent ?这是否确认以下内容是等效的?

(A) (一种)

X x1;
X x2 = static_cast<X&&>(x1); 

(B) (乙)

X x1;
X x2 = std::move(x1);

Yes there is a very important difference: std::move documents what you want to do.是的,有一个非常重要的区别: std::move记录您想要做什么。 In addition the cast is prone to writing errors like a forgotten & or wrong type X .此外,演员表容易写出错误,比如忘记了&或错误的类型X

As it can be seen, std::move is even less to type.可以看出, std::move输入更少。

In C++11, T&& is an rvalue reference.在 C++11 中, T&&是一个右值引用。 They behave like lvalue references from C++ 98/03.它们的行为类似于 C++ 98/03 中的左值引用。 Their goal - to be a candidate for moving.他们的目标——成为搬家的候选人。 In C++98 this construct can appear in reference collapsing.在 C++98 中,这个结构可以出现在引用折叠中。

std::move - turn expression into an rvalue. std::move - 将表达式转换为右值。 It could have been called rvalue_cast , but wasn't.它可以被称为rvalue_cast ,但不是。

Explicit cast to type T&& is possible in principle.原则上可以显式转换为T&&类型。 The official standard costs some money, but in the ISO/IEC 14882:2011 draft there's this:官方标准要花一些钱,但在ISO/IEC 14882:2011草案中有这样的内容:

5.2.9 Static cast 5.2.9 静态转换

8) 8)

The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) conversions are applied to the operand....左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 的转换应用于操作数....

From a practical point of view, it is more convenient to use std::move .从实用的角度来看,使用std::move更方便。

Consider this example:考虑这个例子:

#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
}

For me, the first approach is:对我来说,第一种方法是:

  • more convenient (should you perform static_cast to const A&& , or to A&& ?)更方便(您应该对const A&&A&&执行static_cast吗?)
  • more explicitly (I can use search in text editor to find std::move in the project)更明确(我可以在文本编辑器中使用搜索来查找项目中的std::move
  • less error-prone.不易出错。

They are not strictly equivalent.它们不是严格等效的。 std::move() 's implementation relies on static_cast : std::move()的实现依赖于static_cast

template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

They differ in the sense that std::move() has remove_reference to deal with reference collapse .它们的不同之处在于std::move()remove_reference来处理引用崩溃 An example where (A) and (B) are not strictly equivalent: (A) 和 (B) 不严格等效的示例:

// Set up different behavior for lvalue and rvalue.
class T {};
void func(T&& t) { std::cout << "rvalue captured.\n"; }
void func(T& t) { std::cout << "lvalue captured.\n"; }
// Example:
Using X = T&;
X x1;
X x2 = static_cast<X&&>(x1); // (A) "lvalue captured."
X x3 = std::move(x1);        // (B) "rvalue captured."

You can use static_cast<A &&>(a) when a is an rvalue, but you shouldn't use std::move(a) .当 a 是右值时,您可以使用static_cast<A &&>(a) ,但不应使用std::move(a)
When you use A && a = std::move(A()) , you get a dangling reference.当您使用A && a = std::move(A()) ,您会得到一个悬空引用。

The basic idea is that the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.基本思想是不能通过“传递”来进一步延长临时文件的生命周期:从临时文件绑定的引用初始化的第二个引用不会影响其生命周期。

std::move 's implementation is somewhat like 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM