为什么引用无法捕获临时而const ref和rval ref可以

Tri*_*tos 2 c++ reference rvalue-reference const-reference

为什么引用无法捕获临时值,而const引用和右值引用可以捕获并延长对象的生命周期.换句话说,虽然两个第一行是合法的但第三行不是:

const string &a = string("a");
string &&b = string("b");
string &c = string("c"); // why illegal?
Run Code Online (Sandbox Code Playgroud)

How*_*ant 7

引自N1377

Bjarne在他的优秀文本"C++的设计和演变"中讨论了在3.7节中禁止将rvalue绑定到非const引用的动机.显示以下示例:

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

void g()
{
    double ss = 1;
    incr(ss);
}
Run Code Online (Sandbox Code Playgroud)

ss不会递增,因为必须创建临时int以传递给incr().作者想要事先说明我们同意100%的分析.霍华德甚至被早期编译器咬过这个"虫子".他花了很长时间来追踪正在发生的事情(在这种情况下,它是从浮动到双重的隐式转换,创造了临时).

从C++的曙光到C++ 11(2011),这个理论基础(不将rvalues绑定到非const(左值)引用).但是,相同的基本原理不适用于对const的左值引用:

将临时值绑定到const的左值引用是"安全的",因为编译器会告诉您是否意外地对此临时值进行了"无用"修改.

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

再次引用N1377:

话虽如此,我们想补充一点:您不希望将临时绑定到非const引用...除非您这样做.

非const引用并不总是旨在成为"out"参数.考虑:

template <class T>
class auto_ptr
{
public:
    auto_ptr(auto_ptr& a);
    ...
};
Run Code Online (Sandbox Code Playgroud)

"copy"构造函数采用名为"a"的非const引用.但是修改"a"并不是这个功能的主要目标.主要目标是通过窃取"a"来构建新的auto_ptr.如果"a"碰巧引用右值,则这不是逻辑错误!

总之,有时您想要修改右值,有时则不需要.不同类型的引用允许程序员告诉编译器它们处于哪种情况.

您的问题中的绑定是N1377推动的绑定的逻辑结论.

移动语义提案确实努力提出一个不需要语言更改的解决方案(即引入rvalue引用).但是,仅库解决方案并不令人满意,因为构建诸如移动构造函数之类的结果语法过于复杂.