引用自N1377 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Binding%20temporaries%20to%20references
Bjarne 在他的优秀著作《C++ 的设计与演化》中
讨论禁止将右值绑定到
第 3.7 节中的非常量引用。显示以下示例:
void incr(int& rr) {rr++;}
void g()
{
double ss = 1;
incr(ss);
}
ss 不会递增,因为必须创建一个临时 int 才能传递给
增量()。作者想说我们同意这一点
分析100%。霍华德早年甚至被这个“虫子”咬过一次
编译器。他花了很长时间才弄清楚发生了什么(在那
情况是从 float 到 double 的隐式转换创建了
临时的)。
这个基本原理(不将右值绑定到非常量(左值)引用)从 C++ 诞生之初一直持续到 C++11 (2011)。然而,同样的原理不适用于 const 的左值引用:
将临时对象绑定到 const 的左值引用是“安全”的,因为编译器会告诉您是否不小心对此临时对象进行了“无用”的修改。
那么为什么将右值绑定到右值引用是“安全”的呢?
再次引用自N1377 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Binding%20temporaries%20to%20references:
话虽如此,我们想补充一点:你永远不想绑定一个
临时到非常量引用......除非你这样做。
非常量引用并不总是作为“out”参数。
考虑:
template <class T>
class auto_ptr
{
public:
auto_ptr(auto_ptr& a);
...
};
“复制”构造函数采用名为“a”的非常量引用。但是
修改“a”不是此函数的主要目标。这
主要目标是通过窃取“a”来构造一个新的 auto_ptr。如果一个”
碰巧引用了一个右值,这不是逻辑错误!
总之,有时您想要修改右值,有时则不想。不同类型的引用允许程序员告诉编译器它们处于哪种情况。
您问题中的绑定是 N1377 激发的绑定的逻辑结论。
移动语义提案确实致力于提出一个不需要更改语言的解决方案(即引入右值引用)。然而,仅库的解决方案并不令人满意,因为用于构建诸如移动构造函数之类的东西的语法过于复杂。