void func()
{
Thing t;
work_on(t); // <--- POINT 1
work_on(move(t)); // <--- POINT 2
work_on(Thing()); // <--- POINT 3
}
t
POINT 1 处的表达式是lvalue
.
move(t)
POINT 2 处的表达式是xvalue
.
Thing()
第3 点的表达式是 a prvalue
。
基于表达式的此值类别,从重载集中选择最佳可行函数。
假设两个可用的功能是:
work_on(const Thing&); // lvalue reference version
work_on(Thing&&); // rvalue reference version
Anlvalue
将选择左值引用版本,并且永远不会绑定到右值引用版本。
xvalue
or prvalue
(统称为rvalues
)将有效地绑定到任何一个,但如果可用,将选择右值引用版本作为更好的匹配。
在两个版本的实现内部work_on
,参数基本相同。这样做的目的是右值引用版本可以假设参数是他们的修改或移动。所以它可能会在其参数上调用移动构造函数——而左值引用版本不应该。
所以假设我们有一些vector<Thing> V
应该work_on
将它们的参数添加到:
void work_on(Thing&& t)
{
V.push_back(move(t));
}
void work_on(const Thing& t)
{
V.push_back(t);
}
std::vector::push_back
以与 类似的方式work_on
重载,并且发生类似的重载决议. 在 的两个不同实现中push_back
,右值引用版本将调用移动构造函数将值推送到其数组中,可能会破坏t
. 左值引用版本将调用复制构造函数,保持t
不变。
这种语言机制的主要目的只是跟踪变量(左值)、有意标记的过期值(xvalues)和临时值(prvalues)——因此我们知道何时可以安全地重用它们的资源(移动它们)以及何时可以复制他们。