移动语义的概念是你可以从另一个临时对象(由rvalue引用引用)中获取一切,并将那个"一切"存储在你的对象中。这有助于避免深度复制,其中单个构造足够 -- 所以你在rvalue对象中构造事物,然后只需将其移动到生存时间更长的对象中。
为什么C++不允许将左值对象绑定到rvalue引用?两者都允许我更改所引用的对象,因此在访问所引用的对象的内部方面对我来说没有区别。
我唯一能猜测的原因是函数重载模糊问题。
移动语义的概念是你可以从另一个临时对象(由rvalue引用引用)中获取一切,并将那个"一切"存储在你的对象中。这有助于避免深度复制,其中单个构造足够 -- 所以你在rvalue对象中构造事物,然后只需将其移动到生存时间更长的对象中。
为什么C++不允许将左值对象绑定到rvalue引用?两者都允许我更改所引用的对象,因此在访问所引用的对象的内部方面对我来说没有区别。
我唯一能猜测的原因是函数重载模糊问题。
Class object(much,state,many,members,wow);
looks_safe_to_me(object);
// oh no, it destructively copied my object!
对比
Class object(much,state,many,members,wow);
obviously_destructive(std::move(object));
// same result, but now the destruction is explicit and expected
术语说明:让我们看看上面关于lvalue,rvalue等术语的不准确使用是否可以澄清。
为了记录,引用cppreference:
一个表达式,具有身份且无法移动。
因此,不存在lvalue对象,但是存在由lvalue表达式本地命名(或引用)的对象。
一个表达式,可以是prvalue或xvalue。它们可以被移动。它们可能具有身份,也可能没有。
prvalue(纯rvalue)大致是指引用未命名临时对象的表达式:我们不能将lvalue表达式转换为其中之一(如果我理解正确)。
xvalue(到期值)是
一个表达式,具有身份并且可以被移动。
这明确包括std::move
的结果。
所以实际发生的是:
std::move
产生一个xvalue表达式(可移动),引用与lvalue表达式相同的对象std::move
)显式移动。std::move
时,您并不是将rvalue引用绑定到lvalue上。您正在将lvalue强制转换为rvalue,然后将rvalue引用绑定到它上。 - Jerry Coffinobject
是一个左值,表达式std::move(object)
是一个右值。 - TartanLlama有些历史(追溯到C++的早期)解释了为什么临时对象一开始不能绑定到非const左值引用...细节有点模糊,但是有一些理由是因为修改临时对象没有意义,因为它会在当前语句结束时被销毁。此外,你可能会误以为自己正在修改一个左值,而实际上不是这样——代码的语义可能/会出错并导致错误。还有其他原因与地址、文字等有关。这是在移动及其语义确立之前,也是移动和其语义的一些动机。
T&&
之前,可以使用引用来修改传递的对象(无论发生何种修改都不重要)。这意味着在每种情况下,当传递一个非const引用时,都应该检查传递的实体发生了什么。他们实际上试图建立T&
不应该被修改(即其内容不应被获取)的概念。这个概念是错误的。应该使用const T&
来实现这一点。 - Kirill Kobelev
void foo(vector & bar) {} foo(create temp vector here);
? - NathanOliverstd::move
吗? - Jarod42void foo(vector&& bar) {} foo(already existing vector);
;-) - L. F.