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)
引自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引用).但是,仅库解决方案并不令人满意,因为构建诸如移动构造函数之类的结果语法过于复杂.