【问题标题】:Why reference can not capture temporary while const ref and rval ref can [duplicate]为什么引用不能临时捕获,而 const ref 和 rval ref 可以[重复]
【发布时间】:2014-09-21 10:17:32
【问题描述】:

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

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

【问题讨论】:

  • 你打算用它做什么?修改它并将更改传播给任何人?
  • @chris 我会用它来优化。
  • 那会是什么优化?
  • 副本没有解决这个问题提出的关于右值引用的部分。
  • @chris 你打算做什么右值引用可以用来代替常规引用?为什么标准不问这样的问题?您仍然可以将右值引用不仅用于类似 std::move 的操作,还可以作为我所介绍的上下文中常规引用的替代品。您的 const 引用也可以延长寿命。为什么延长 const 对象的生命周期而不延长非 const 对象的生命周期?

标签: c++ reference rvalue-reference const-reference


【解决方案1】:

引用N1377

Bjarne 在他的优秀著作《C++ 的设计与演进》中 讨论禁止将右值绑定到 第 3.7 节中的非常量引用。如下示例所示:

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

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

ss 不会增加,因为必须创建一个临时 int 才能传递给 增量()。作者想在前面说我们同意这一点 分析 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。如果一个” 碰巧引用了一个右值,这不是逻辑错误!

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

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

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

【讨论】:

  • 也许补充一点,将普通引用用于移动语义的内在危险是引入 r 值引用的基本原理,并且在这样做时auto_ptr 立即被弃用为不安全?
  • @Deduplicator:感谢您的建议。我又加了一段,看你怎么想。如果我的回答还不清楚,很高兴再试一次。
  • 现在可以使用右值引用来破坏 N1377 中的示例代码。所以他们无论如何都引入了描述的危险行为,这是引入移动语义的代价。
  • @Trismegistos 如果您使用右值引用,那么您知道您正在使用临时(或调用者希望您将其视为临时的)。
  • @Trismegistos:你永远不想修改临时......除非你这样做。 :-)
猜你喜欢
  • 1970-01-01
  • 2020-11-10
  • 2014-09-09
  • 1970-01-01
  • 2014-06-14
  • 2015-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多