我有一个异步函数foo_async
,它接受一个回调(lambda)并在按值捕获后在新线程上执行它。
void foo_async(const std::function<void()>& callback)
{
std::thread t([callback]() // capture callback by value
{
callback();
});
t.detach();
}
我在函数bar
中使用它本身需要回调
void bar(const std::function<void()>& callback)
{
auto barCallback = [callback] // capture original callback by value
{
callback();
std::cout << "world" << std::endl;
};
foo_async(barCallback);
}
最后,我从bar
main
int main()
{
std::string s("hello ");
bar([s]{ std::cout << s; }); // capture some state
std::cin.get();
}
我遇到的问题是s
中的字符main
被复制三次,一次放入main
,一次放入bar
,一次放入foo_async
。但理想情况下,应该只需要将它复制两次 - 在main
中将其放入lambda,在foo_async
中复制以在另一个线程上执行。 bar
中的副本应该已经避免,因为它同步执行。
有什么方法可以避免s
的额外副本吗?请注意,我无法通过bar中的引用捕获原始回调,因为foo_async需要在新线程上执行它。
答案 0 :(得分:0)
您可以尝试两件事:1)不要保留lambda的本地副本,2)将函数对象移动到lambdas中:
void foo_async(std::function<void()> callback)
{
std::thread([c = std::move(callback)]() { c(); }).detach();
}
void bar(std::function<void()> callback)
{
foo_async([c = std::move(callback)]() { c(); std::cout << "world\n"; });
}
int main()
{
std::string s("hello ");
bar([s = std::move(s)]{ std::cout << s; });
}