2

为什么引用不能捕获临时值,而 const 引用和右值引用可以捕获并延长对象寿命。换句话说,虽然前两行是合法的,但第三行不合法:

const string &a = string("a");
string &&b = string("b");
string &c = string("c"); // why illegal?
4

1 回答 1

8

引自N1377

Bjarne 在其出色的文章“C++ 的设计和演变”中讨论了在第 3.7 节中禁止将右值绑定到非 const 引用的动机。显示以下示例:

void incr(int& rr) {rr++;}

void g()
{
    double ss = 1;
    incr(ss);
}

ss 不会递增,因为必须创建一个临时 int 才能传递给 incr()。作者想说的是,我们 100% 同意这一分析。霍华德甚至被早期编译器的这个“错误”所困扰。他花了很长时间才弄清楚发生了什么(在这种情况下,是从浮点数到双精度数的隐式转换创建了临时)。

这个基本原理(不将右值绑定到非常量(左值)引用)从 C++ 诞生之初就一直存在,直到 C++11(2011 年)。然而,同样的理由不适用于对 const 的左值引用:

将临时值绑定到对 const 的左值引用是“安全的”,因为编译器会告诉您是否不小心对此临时值进行了“无用”修改。

那么为什么将右值绑定到右值引用是“安全的”呢?

再次引用N1377

话虽如此,我们想补充一点:您永远不想将临时对象绑定到非常量引用......除非您这样做。

非常量引用并不总是旨在成为“out”参数。考虑:

template <class T>
class auto_ptr
{
public:
    auto_ptr(auto_ptr& a);
    ...
};

“复制”构造函数采用名为“a”的非常量引用。但是修改“a”并不是这个函数的主要目标。主要目标是通过窃取“a”来构造一个新的 auto_ptr。如果“a”碰巧引用了一个右值,这不是一个逻辑错误!

总之,有时你想修改一个右值,有时你不想。不同类型的引用允许程序员告诉编译器他们处于哪种情况。

您问题中的绑定是由 N1377 激发的绑定的合乎逻辑的结论。

移动语义提案确实致力于提出一个不需要更改语言的解决方案(即引入右值引用)。然而,仅库的解决方案并不令人满意,因为构建诸如移动构造函数之类的东西的语法过于复杂。

于 2014-07-29T22:02:13.930 回答