为什么这个代码工作/失败取决于范围闭包创建在?

时间:2015-11-26 07:16:40

标签: c++ templates closures

以下代码在另一个回调中包装了一个回调函数,但是根据内部回调的范围,代码要么成功还是失败了。

下面的代码按原样运行正常,但如果回调是在main内而不是直接在frame #110339: 0x000000010000453c a.out`std::__1::__function::__func<void stuff<B>(std::__1::function<void (B*)>)::'lambda'(A*), std::__1::allocator<void stuff<B>(std::__1::function<void (B*)>)::'lambda'(A*)>, void (A*)>::operator()(A*&&) + 60 frame #110340: 0x0000000100002fdf a.out`std::__1::function<void (A*)>::operator()(A*) const + 159 中完成的,则代码会失败:

#include <functional>
#include <list>

class A {
public:
  virtual ~A(){}
};

class B : public A {
public:
  virtual ~B(){}
};


std::list<std::function<void(A*)>> callbacks;
void stuff(std::function<void(A*)> callback){
  callbacks.push_back(callback);
  printf("Now have %d callbacks\n", (int)callbacks.size());

}

template<typename T>
void stuff(std::function<void(T*)> callback) {


  stuff([&](A* a) {
      T * b = dynamic_cast<T*>(a);
      if (b!= nullptr) {
        printf("Calling actual callback\n");
        callback(b);
      } else {
        printf("Not calling actual callback\n");
      }
    }
    );
}

void make_callback()
{
  stuff<B>([&](B*b){printf("Hello with a B\n");});
}

int main()
{
  //make_callback();                                                                                                 
  stuff<B>([&](B*b){printf("Hello with a B\n");});

  A a;
  B b;
  for (auto callback : callbacks) {
    callback(&a);
    callback(&b);
  }
}

代码:

$con

1 个答案:

答案 0 :(得分:2)

由于您在stuff模板中进行了引用捕获,callback是调用该函数时的悬空引用。 (它指的是参数,参数的生命周期已经结束。)
与往常一样,使用悬挂引用是未定义的,可能会或可能不会起作用。

此代码中无需参考捕获。