4

我有一个程序,我不能使用标准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

4

1 回答 1

4

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

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

如果您希望它在函数结束后继续存在,则不能将其生命周期与函数绑定:您需要动态存储持续时间。Astd::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. 见GOTW #make_unique 102 。

于 2012-04-27T21:18:29.713 回答