4

我的编译器是最新的 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);?

4

2 回答 2

3

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

简短的回答:从来没有,无处可去,原因如下:

所有命名变量表达式都是左值。因此,它所做的就是采用big_obj左值,将其强制转换为 xvalue,并使用它来初始化只能用作左值的右值引用,然后我们回到开始的地方。这是一个完全没用的代码行。

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

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

Bjarne 在 GoingNative2013 的问答环节中给出的建议基本上是,不要尝试将右值引用用于比移动构造函数和移动赋值运算符更“聪明”的东西。

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

于 2013-09-12T16:27:52.717 回答