即将推出的C++标准C++0x的一个很酷的新特性是“右值引用”。右值引用类似于左值(正常)引用,不同之处在于它可以绑定到临时值(通常,临时值只能绑定到const
引用):
void FunctionWithLValueRef(int& a) {…}
void FunctionWithRValueRef(int&& a) {…}
int main() {
FunctionWithLValueRef(5); // error, 5 is a temporary
FunctionWithRValueRef(5); // okay
}
那么,为什么他们发明了一种全新的类型,而不是仅仅取消对普通引用的限制,以允许它们绑定到临时引用?
发布于 2009-05-09 22:58:53
这将是毫无意义的。您将在函数中更改该内容,并且更改将立即丢失,因为该内容实际上是临时的。
使用新类型的原因是需要能够确定什么是rvalue,什么不是。只有这样,你才能真正使用它们来做一些很酷的事情。
string toupper(string && s) { // for nonconst rvalues
for(char &c : s) make_uppercase(c);
return move(s); // move s into a returned string object
}
string toupper(string const& s) { // for the rest
// calls the rvalue reference version, by passing
// an rvalue copy.
return toupper(string(s));
}
现在,如果您有一些rvalue并将其传递给toupper,则可以直接修改rvalue,因为我们知道临时值无论如何都是一个丢弃的东西,所以我们也可以直接更改它,而不需要复制它。同样,同样的观察也被用于移动构造函数和移动赋值函数。右侧没有被复制,但它的内容只是被偷走并移动到*this
。
如果您说rvalue可以绑定到非常量左值引用,那么您将无法确定最终引用的是lvalue (命名对象)还是rvalue(临时对象)。
它可能更少人知道,但无论如何都很有用,您可以将左值或右值引用限定符放在成员函数上。下面是一个示例,它自然地将rvalue引用的现有语义扩展到隐式对象参数:
struct string {
string& operator=(string const& other) & { /* ... */ }
};
现在,你不能再说
string() = "hello";
这在大多数情况下是令人困惑的,也没有真正的意义。上面的&
所做的是说明赋值运算符只能在左值上调用。对右值也可以这样做,只需放入&&
。
发布于 2009-05-09 22:59:13
因为添加新类型的引用允许您编写方法的两个重载:
void CopyFrom(MyClass &&c)
{
dataMember.swap(c);
}
void CopyFrom(const MyClass &c)
{
dataMember.copyTheHardWay(c);
}
接受新类型引用的版本可以修改它接收的变量,因为该变量不会在其他任何地方使用。所以它可以“窃取”其中的内容。
这就是添加此功能的全部原因;保留一种类型的引用不会达到预期的目标。
https://stackoverflow.com/questions/844241
复制相似问题