C++11:基于范围的 for 语句:“range-init”生命周期?

Posted

技术标签:

【中文标题】C++11:基于范围的 for 语句:“range-init”生命周期?【英文标题】:C++11: The range-based for statement: "range-init" lifetime? 【发布时间】: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()" 是返回集合的示例函数的签名。然后在下面的行中调用该函数。 【参考方案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 循环中使用此值会导致未定义的行为。

【讨论】:

以上是关于C++11:基于范围的 for 语句:“range-init”生命周期?的主要内容,如果未能解决你的问题,请参考以下文章

我应该在基于 C++11 范围的 QHash::keys() 上使用 qAsConst

C++11-范围for(range for)

C++11的for循环,以及范围Range类的实现

C++11新特性:14—— C++11 for循环(基于范围的循环)详解

错误:C++98 模式下不允许基于范围的“for”循环

4/26打卡,范围for循环