难道rvalue不应该是"临时的"吗,也就是说,在表达式结束时将变得无效吗?
不,它们不是。
假设你有一个函数 f
,这个也是合法的:
T t{};
T&& y = f(std::move(t));
这是完全有效的C++11代码。并且发生的情况也是定义明确的。
你的代码之所以未定义是因为传递了一个临时对象。但是,r-value引用不一定是临时对象。
更详细地说,r-value引用在概念上是对一个值的引用,从中可以进行某些操作,而这些操作在其他情况下是不被允许的。
C++11非常仔细地规定了r-value引用。l-value引用可以绑定到任何非临时对象,无需进行任何强制转换或其他操作:
T t{};
T &y = t;
一个右值引用只能隐式地绑定到一个临时对象或其他的“xvalue”(即一个很可能在不久的将来就会消失的对象):
T &&x = T{};
T &&no = t; //Fail.
为了将一个右值引用绑定到非 xvalue,你需要进行显式转换。C++11 中的这种转换方式很明显,使用
std::move
。
T &&yes = std::move(t)
我所说的“特定操作”是“移动”。只有在以下两种情况下才可以从对象中移动:
1. 它将要离开。例如:临时变量。
2. 用户明确表示要从它移动。
这些是唯一两种r值引用可以绑定到某些东西的情况。
r值引用存在的唯二原因是支持移动语义和支持完美转发(需要一种新的引用类型,可以将其钩子式转换机制挂接到其中,以及潜在的移动语义)。因此,如果没有进行这两个操作之一,则使用“&&”的原因是可疑的。
T
初始化T &&
。 - lapkstatic_cast<T&&>(x)
,所以现在它可以编译。 - Clinton