在页面How to: Write a Move Constructor上,Microsoft有一个关于如何编写移动构造函数的示例。它基本上是以下形式:
MyClass::MyClass(MyClass&& lhs)
{
*this = std::move(lhs);
}
我试过了,std::move
确实需要,但为什么呢?我认为唯一的举动就是转换为T&&
。但lhs
已经是MyClass&&
类型,不是吗?
答案 0 :(得分:20)
命名的右值引用是左值。未命名的右值引用是右值。这对于理解为什么std :: move调用在以下内容中非常重要:
foo&& r = foo(); foo f = std::move(r);
看看这个答案:https://stackoverflow.com/a/5481588/1394283它解释得非常好。
看看这个功能:
void foo(X&& x)
{
X anotherX = x;
// ...
}
有趣的问题是:在X
的主体中调用了foo
的复制构造函数的重载?这里,x
是一个声明为右值引用的变量。因此,期望x
本身也应该像rvalue一样绑定是很合理的,也就是说,
应该调用X(X&& rhs);
。
允许将移动sematics默认应用于具有名称的内容,如
X anotherX = x;
// x is still in scope!
会带来危险的混乱和容易出错,因为我们刚刚移动的东西,即我们刚刚窃取的东西,仍然可以在后续的代码行中访问。 但是移动语义的全部意义只是在它“无关紧要”的地方应用它,因为我们移动的东西会在移动后立即消失并消失。
这就是为什么rvalue引用的设计者选择了一个比这更微妙的解决方案的原因:
声明为右值参考的事物可以是左值或右值。区别标准是:如果它有一个名字,那么它就是一个左值。否则,它是一个右值。
来源:http://thbecker.net/articles/rvalue_references/section_05.html