我有一个程序,我无法使用标准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);
}
Run Code Online (Sandbox Code Playgroud)
我现在想知道我做得是否正确,或者使用 lambda 作为异步回调的最佳方法是什么。
编辑:在代码注释中添加了预期的行为。有关 问题的可能解决方案,请参阅答案/评论blub。
函数对象将包含对局部变量的引用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
Run Code Online (Sandbox Code Playgroud)
作为补充说明,旧的已弃用的std::auto_ptr实际上在这里可以正常工作,因为如果 lambda 按值捕获它,它就会被复制,并且其奇怪的复制语义正是所需要的。
1. 请参阅GOTW #102make_unique。