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

时间:2012-03-11 18:33:26

标签: c++ c++11

在最新的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&amp;&amp; r = boo()”的末尾被销毁,然后r是循环入口处的挂起引用。 ??这个推理是否正确?如果没有,为什么不呢?

2 个答案:

答案 0 :(得分:16)

  

这种推理是否正确?如果没有,为什么不呢?

到目前为止这是正确的:

  

所以boo()的临时返回值在语句“auto&amp;&amp; r = boo()”[...]

的末尾被销毁

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

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

  

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

     

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

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

答案 1 :(得分:6)

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

  

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

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