关于C ++右值引用(http://www.artima.com/cppsource/rvalue.html)的关于Artima的文章,有一些词:这就是为什么在传递给基类时有必要说move(x)而不是x。这是移动语义的一个关键安全功能,旨在防止意外地从某个命名变量移动两次。
当这样的双重动作可以执行时,我无法想到这种情况。你能举个例子吗?换句话说,如果T&&
的所有成员都是右值引用而不仅仅是引用,会出现什么问题?
答案 0 :(得分:16)
考虑这种情况:
void foo(std::string x) {}
void bar(std::string y) {}
void test(std::string&& str)
{
// to be determined
}
我们希望foo
使用str
,然后bar
使用str
,两者都具有相同的值。最好的方法是:
foo(str); // copy str to x
bar(std::move(str)); // move str to y; we move it because we're done with it
这样做是错误的:
foo(std::move(str)); // move str to x
bar(std::move(str)); // move str to y...er, except now it's empty
因为在第一次移动后,str
的值未指定。
因此在rvalue引用的设计中,这种隐式移动并不存在。如果是这样,我们上面的最佳方式就行不通,因为第一次提到str
会改为std::move(str)
。
答案 1 :(得分:3)
我看到它的方式是,如果我们有一些右值参考x:
T&& x = ...;
我们使用x作为参数调用了一些函数:
f(x)
我们需要告诉f它是否会损坏x(或“取得x的所有权”,或“是最后一个使用x的客户”)。
设计此方法的一种方法是限定每次通话:
f(yours_now(x)) // ok to damage
f(still_mine(x)) // dont damage
并使不合格的电话非法。
另一种方法是将一种方式设为默认值:
或者:
f(yours_now(x)) // ok to damage
f(x) // dont damage
或
f(x) // ok to damage
f(still_mine(x)) // dont damage
因此,如果我们同意资格认证,每次使用都太笨重,我们应该默认为一种方式,哪种方式最好?好吧,让我们看看两种情况下意外选择默认值的成本:
在第一种情况下它可以损坏,但我们不小心说它不是。在这种情况下,我们失去了性能,因为制作了不必要的副本,但除此之外没什么大不了的。
在第二种情况下,不能破坏物体,但我们不小心说它是。这可能会导致难以检测到程序中的逻辑错误,因为当f返回时x现在处于损坏状态,但作者预计它不会出现。
所以第一种情况是选择的,因为它“更安全”。