Zif*_*fre 20 c++ rvalue lvalue c++11
即将推出的C++标准C++ 0x的一个很酷的新特性是"右值引用".右值引用类似于左值(正常)引用,但它可以绑定到临时值(通常,临时值只能绑定到const引用):
void FunctionWithLValueRef(int& a) {...}
void FunctionWithRValueRef(int&& a) {...}
int main() {
FunctionWithLValueRef(5); // error, 5 is a temporary
FunctionWithRValueRef(5); // okay
}
Run Code Online (Sandbox Code Playgroud)
那么,为什么他们发明了一种全新的类型,而不仅仅是删除对普通引用的限制以允许它们绑定到临时版本?
Joh*_*itb 43
这将毫无意义.您将更改函数中的内容,并且更改将立即丢失,因为该内容实际上是临时的.
新类型的原因在于需要能够确定实际上是什么是右值,什么不是.只有这样,你才能真正使用它们来实现它们所使用的很酷的东西.
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));
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你有一些rvalue并将它传递给toupper,那么rvalue可以直接修改,因为我们知道临时是一个扔掉的东西,所以我们也可以改变它而不需要复制它.此外,同样的观察用于称为移动构造函数和移动赋值的东西.右手边没有被复制,但是它的东西被偷走了并移动到了*this.
如果你说rvalues可以绑定到非const左值引用,那么你无法弄清楚它是否在最后引用了左值(命名对象)或右值(临时).
它可能知之甚少,但无论如何,你可以将lvalue或rvalue ref-qualifiers放在成员函数上.这是一个示例,它自然地将rvalue引用的现有语义扩展为隐式对象参数:
struct string {
string& operator=(string const& other) & { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
现在,你再也不能说了
string() = "hello";
Run Code Online (Sandbox Code Playgroud)
这是令人困惑的,并且在大多数时候并没有真正有意义.什么&上述声明是说,赋值运算符只能在左值调用.通过推杆,对于右值也可以做同样的事情&&.
Dan*_*ker 12
因为添加新类型的引用允许您编写方法的两个重载:
void CopyFrom(MyClass &&c)
{
dataMember.swap(c);
}
void CopyFrom(const MyClass &c)
{
dataMember.copyTheHardWay(c);
}
Run Code Online (Sandbox Code Playgroud)
接受新类型引用的版本允许修改它接收的变量,因为该变量不会在其他任何地方使用.所以它可以"窃取"它的内容.
这是添加此功能的全部原因; 保留一种参考类型将无法实现预期目标.