如何在调用异步函数时采用lambda回调来避免额外的副本

时间:2014-11-18 23:12:32

标签: c++ c++11 asynchronous visual-studio-2013 copy

我有一个异步函数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需要在新线程上执行它。

1 个答案:

答案 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; });
}