正如许多其他帖子所解释的那样,将一个变量声明为右值引用不能保证它将调用 move 赋值运算符,仅使用 std::move
(即也就是说,转换为相同的右值引用)就可以了。例如:
struct A
{
A& operator=(A&& l_other) { std::cout << "move" << std::endl; }
A& operator=(A& l_other) { std::cout << "copy" << std::endl; }
};
A a;
// does not print anything, compiler does nothing here!
A&& b = std::move(a);
// prints "copy", not "move"
a = b;
// prints "move", but needs std::move()
a = std::move(b);
似乎将 b
定义为 A&&
在那一刻不会 move 任何东西。之后,a = b
不会自动 move b
,即使右侧部分被定义为 A&&
,正如其他帖子所解释的那样。我们需要显式调用 std::move(b)
来 move b
。
我的问题是,将变量定义为 A&&
有什么用处?我可以完美地将其定义为 A&
并将其精确 move 到一样。
最佳答案
My question is, what's the utility of defining a variable as A&&? I could perfectly define it as A& and move it exactly the same.
如果将命名变量传递到函数中并像这样进行修改而不发出警告,这是非常令人不快的,并且可能会导致令人不快的调试 session 。
当您使用右值引用时,类型系统会强制执行有用的保证。要么引用绑定(bind)到一个右值,所以修改它不会违反任何人的假设(无论如何它很快就消失了)。或者您已获得明确许可搬出。调用上下文不能意外地授予您修改左值的权限,它必须通过显式强制转换 (std::move
) 来执行此操作。
显式优于隐式。让右值引用以它们的方式与类型系统交互有助于确保 move 不会使对象处于意外状态。看一眼调用上下文就会发现,传递到函数中的变量可能处于未知状态,因为它显式地包含对 std::move
的调用。
这就是右值引用的好处。
关于c++ - 如果右值引用确实需要 std::move,我们应该什么时候声明它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58854278/