【问题标题】:C++11: The range-based for statement: "range-init" lifetime?C++11:基于范围的 for 语句:“range-init”生命周期?
【发布时间】:2012-03-11 18:33:26
【问题描述】:

在最新的 C++ 标准中,它暗示:

for (foo : bar)
    baz;

等价于:

{
    auto && r = bar;
    for ( auto it = r.begin(), end = r.end(); it != end; ++it )
    {
        foo = *it;
        baz;
    }
}

当上面的bar是一个返回集合的函数调用时,例如:

vector<string> boo();

for (auto bo : boo())
    ...

这条线不就变成了:

auto&& r = boo();
...

于是 boo() 的临时返回值在语句“auto&&r=boo()”的末尾被销毁,然后 r 是循环入口处的挂起引用。 ??这个推理正确吗?如果没有,为什么不呢?

【问题讨论】:

  • 首先,vector&lt;string&gt; boo(); 没有声明对象。它声明了一个函数。其次,我不明白你的问题。
  • Yes "vector boo()" 是返回集合的示例函数的签名。然后在下面的行中调用该函数。

标签: c++ c++11


【解决方案1】:

这个推理正确吗?如果没有,为什么不呢?

到目前为止都是正确的:

因此 boo() 的临时返回值在语句“auto&&r=boo()”的末尾被销毁 [...]

将临时对象绑定到引用可将其生命周期延长为引用的生命周期。所以临时文件持续整个循环(这也是为什么在整个构造周围有一组额外的{}:正确限制该临时文件的生命周期)。

这是根据 C++ 标准 §12.2 的第 5 段:

第二个上下文是引用绑定到临时的。这 引用绑定到的临时对象或作为临时对象的临时对象 引用绑定到的子对象的完整对象 在引用的生命周期内持续存在,除了:

[此处不适用的各种例外情况]

这是一个有趣的属性,它允许滥用 ranged-for 循环来处理非范围的事情:http://ideone.com/QAXNf

【讨论】:

    【解决方案2】:

    推理不正确,因为boo 按值返回一个临时对象。将此临时对象绑定到引用意味着延长临时对象的生命周期。标准报价(§ 12.2/5):

    […] 引用绑定到的临时对象或引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在 […]

    如果boo 返回引用,则推理是正确的。一个返回临时引用的表达式的例子是string("a") += string("b");在基于范围的 for 循环中使用此值会导致未定义的行为。

    【讨论】:

      猜你喜欢
      • 2012-02-18
      • 1970-01-01
      • 2015-08-07
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      相关资源
      最近更新 更多