使用lambdas作为异步回调

时间:2012-04-27 11:12:50

标签: c++ c++11 lambda

我有一个程序,我无法使用标准std::async和线程机制。相反,我必须像这样编写程序:

void processor( int argument, std::function<void(int)> callback ) {
  int blub = 0;

  std::shared_ptr<object> objptr = getObject();

  // Function is called later.
  // All the internal references are bound here!
  auto func = [=, &blub]() {
    // !This will fail since blub is accessed by reference!
    blub *= 2;

    // Since objptr is copied by value it works.
    // objptr holds the value of getObject().
    objptr->addSomething(blub);

    // Finally we need to call another callback to return a value
    callback(blub);
  };

  objptr = getAnotherObject();

  // Puts func onto a queue and returns immediately.
  // func is executed later.
  startProcessing(func);
}

我现在想知道我是做得对还是使用lambdas作为异步回调的最佳方法是什么。

编辑:在代码注释中添加了预期的行为。 有关blub的问题的可能解决方案,请参阅答案/评论。

1 个答案:

答案 0 :(得分:4)

函数对象将包含对局部变量blub的引用。 与语言中的所有其他情况一样,在函数结束后,这不会使局部变量生效。

所有其他捕获对象的副本将存储在函数对象中,因为它们是按值捕获的。这意味着它们没有问题。

如果您希望它在函数结束后生效,则无法将其生命周期与函数联系起来:您需要动态存储持续时间std::unique_ptr可以用来处理这样一个对象的清理,但它有点烦人,因为你不能“移动”捕获到一个lambda:S

auto blub = make_unique<int>(0); // [1]

std::shared_ptr<object> objptr = getObject();

// use std::bind to store the unique_ptr with the lambda
auto func = std::bind([=](std::unique_ptr<int>& blub) {
  *blub *= 2;

  objptr->addSomething(*blub);

  callback(*blub);
}, std::move(blub)); // move the unique_ptr into the function object

objptr = getAnotherObject();

// func is not copiable because it holds a unique_ptr
startProcessing(std::move(func)); // move it

作为补充说明,旧的已弃用的std::auto_ptr在这里实际上可以正常工作,因为如果lambda按值捕获它,它会被复制,其奇怪的复制语义正是所需要的。


<子> 1。有关make_unique

,请参阅GOTW #102