何时,何地以及为什么要使用“BigObject&& rv = std :: move(big_obj);”?

时间:2013-09-12 09:38:30

标签: c++ visual-c++ c++11 rvalue-reference

我的编译器是最新的VC ++ 2013预览版。

#include <utility>

struct BigObject { ... };

void f(BigObject&&){}
void f(BigObject&) {}
void f(BigObject)  {}

int main()
{
    BigObject big_obj;

    BigObject&  r1 = big_obj; // OK.
    BigObject&& r2 = big_obj; // error C2440
    BigObject&& r3 = std::move(big_obj); // OK.
    BigObject&& r4 = r3; // error C2440

    f(r3); // error C2668: 'f' : ambiguous call to overloaded function
}

我们何时,何地以及为何要使用BigObject&& rv = std::move(big_obj);

3 个答案:

答案 0 :(得分:3)

我们应该使用BigObject&& rv = std::move(big_obj);的时间,地点和原因?

简短的回答:从来没有,因为以下原因:

所有命名变量表达式都是左值。所以这是在做big_obj,这是一个左值,将它强制转换为xvalue,并使用它来初始化一个rvalue引用,然后只能用作左值,我们又回到了我们的位置开始。这是一个完全没用的代码。

除了函数参数之外,定义局部右值引用通常不是很有用。但它们确实延长了用于初始化它们的临时对象的生命周期,因此它们可能偶尔会在多个语句中分离复杂表达式时使用。

值类别是表达式的属性,而不是引用的属性。您可以根据希望它能够绑定到的表达式的值类别来选择要使用的引用类型。并且使用std::move来强制调用函数的特定重载,否则它将调用错误的函数或模糊不清。

Bjarne在GoingNative2013的Q&amp; A会话期间给出的建议基本上是,不要试图使用rvalue引用来比移动构造函数和移动赋值运算符更“聪明”。

来自Herb Sutter:很多人认为移动意味着在任何地方写&&,但事实并非如此。您不需要自己编写&&,除非您正在编写移动构造函数或移动赋值运算符,或者在函数模板中完美地转发参数。

答案 1 :(得分:0)

除了塞巴斯蒂安·雷德尔的回答:

我认为首先你必须阅读并理解什么是左值,右值? see here

简单地说,rvalue是表达式右侧侧的值,左侧是lvaules值。

int n = 0;
// n is a lvalue
// 0 is a rvalue

第二,您还必须了解什么是参考?

再次简单地说,

引用是(仅)别名的其他变量:

int& r1 = n;
// means r1 ≡ n
cout << &r1 << "=" << &n;

现在&amp;&amp; 表示r2期待一个右值。 std::move是一个类型转换,它将左值转换(如果可能)为右值。

你应该对具有存储在堆上的数据的类型使用move-semantic并且具有移动构造函数ore move赋值。例如,见std::vector。如果要将矢量移动到另一个矢量,指向移动矢量数据的指针将归零nullptr'。

在POD上使用move-semantic是没用的,但是不会伤害你,因为std :: move 只是一个演员。而它等于参考。

请参阅此exaple这个小文章。

答案 2 :(得分:-3)