lambda的生命周期捕获

时间:2014-09-25 13:55:26

标签: c++ lambda

鉴于以下计划:

#include <iostream>
#include <memory>
using namespace std;
int main() {
    std::shared_ptr<int> i(new int(42));
    cout << i.use_count() << endl;
    auto fn = [=](){i; cout << 42 << endl;};
    cout << i.use_count() << endl;
    return 0;
}

编译器何时决定捕获哪些对象? shared_ptr i从未在lambda表达式中使用。因此,在正常函数中,我会假设优化器将删除此nop语句 但如果删除它,编译器可能会认为不需要捕获i

因此,使用gcc,该程序将始终生成1,2作为输出 但这是否由标准保证?

2 个答案:

答案 0 :(得分:2)

如果我们转到lambda function上的cppreference页面,他们会有以下解释:

  

[=]按值

捕获lambda体中提到的所有自动变量

并进一步说:

  

捕获列表是以逗号分隔的零个或多个捕获列表,可选择以capture-default开头。唯一的捕获默认值是&amp; (通过引用隐式捕获odr使用的自动变量)和=(隐式捕获odr使用的自动变量,按值计算)。

odr-used的参考部分说:

  

如果变量的名称显示为可能已评估的表达式,则该变量使用odr,除非以下所有内容都是   真:

     
      
  • 将lvalue-to-rvalue转换应用于exression会产生一个不会调用非平凡函数的常量表达式
  •   
  • 表达式是丢弃值表达式或左值到右值转换
  •   

例外情况不适用于i,因此会捕获i

哪个与draft C++11 standard部分5.1.2 Lambda表达式 11 一致,其中包含:

  

如果lambda表达式具有关联的capture-default及其   复合语句odr-uses(3.2)this或变量with automatic   存储持续时间和odr使用的实体未明确捕获,   然后,据说隐含地捕获了使用过的实体;这样   实体应在lambda的范围内声明   表达

答案 1 :(得分:2)

默认捕获[=],如果它在lambda中 odr-used ,则捕获任何局部变量。 odr-used 的定义是:

  

名称显示为可能已评估的表达式的变量是 odr-used ,除非它是满足出现在常量表达式中的要求的对象,并且lvalue-to-rvalue转换是立即的应用

这里,i是一个评估表达式,并且不是常数;所以它是odr-used因此被捕获;是否评估表达式有任何影响。

  

但这是否由标准保证?

tl;是的。