即使没有使用捕获,也会捕获捕获?

时间:2018-05-18 07:42:55

标签: c++11 lambda destructor

我使用异步函数将对象引用&foo和回调cb作为参数。我希望防止在调用回调之前销毁foo

void async_thing(Foo &foo, function<void()> cb) {
    // do something asynchronously with foo
}

仅仅在回调lambda中捕获它就足够了吗?或者它是否需要在lambda中实际使用

auto foo = make_shared<Foo>();
async_thing(*foo, [foo]() {
    cout << "Callback ran" << endl;
});

编译器是否可以优化捕获,并过早删除foo

1 个答案:

答案 0 :(得分:2)

n3690,第5.1.2节

  

<强> 15   如果隐式捕获实体,则通过副本捕获实体   capture-default is =或者是否通过捕获显式捕获   不包括&amp ;.对于通过复制捕获的每个实体,a   未命名的非静态数据成员在闭包类型中声明。

我们在其上面:

  

第3   lambda表达式的类型(也是表达式的类型)   closure object)是一个唯一的,未命名的nonunion类类型 - 称为   封闭类型。
  [...]
  实现可以定义闭包类型   与下面描述的不同,只要不改变   程序的可观察行为,而不是改变:

     
      
  • 封闭类型的大小和/或对齐方式
  •   
  • 封闭类型是否可以轻易复制(第9条),
  •   
  • 闭包类型是标准布局类(第9条)还是
  •   
  • 闭包类型是否为POD类(第9条)。
  •   

由此我得出结论:

  • 捕获在闭包类型中创建一个shared_ptr成员。
  • 不允许编译器改变该可观察行为。
  • 因此,在调用闭包的析构函数之前,不会删除指针。