为什么C++ 0x rvalue引用不是默认值?

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)

这是令人困惑的,并且在大多数时候并没有真正有意义.什么&上述声明是说,赋值运算符只能在左值调用.通过推杆,对于右值也可以做同样的事情&&.

  • 我想补充一点,http://thbecker.net/articles/rvalue_references/section_01.html是一篇很棒的"关于傻瓜的左右参考"的文章. (2认同)

Dan*_*ker 12

因为添加新类型的引用允许您编写方法的两个重载:

void CopyFrom(MyClass &&c)
{
    dataMember.swap(c);
}

void CopyFrom(const MyClass &c)
{
    dataMember.copyTheHardWay(c);
}
Run Code Online (Sandbox Code Playgroud)

接受新类型引用的版本允许修改它接收的变量,因为该变量不会在其他任何地方使用.所以它可以"窃取"它的内容.

这是添加此功能的全部原因; 保留一种参考类型将无法实现预期目标.