在通过引用捕获时,tu如何异步使用C ++ 11 lambda

时间:2014-06-18 10:43:07

标签: c++11 asynchronous lambda capture

有人可以解释以下代码的行为吗?

当我明确地将我的lambda转换为std::function时,lambda正确地捕获了我的变量n

当隐式转换为std::function(使用临时)时,捕获失败。

我正在使用g++-4.9 (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]

#include <chrono>
#include <iostream>
#include <memory>
#include <thread>

std::shared_ptr<std::thread> call(const std::function<void()>& functor)
{
    // Execute our functor asynchronously
    return std::make_shared<std::thread>([&functor]
    {
        // Make sure all temporary are deallocated
        std::this_thread::sleep_for(std::chrono::seconds(1));
        // Execute our functor
        functor();
    });
}

int main()
{
    int n{};
    std::cout << "in main   " << &n << std::endl;
    // -> in main   0x7fffd4e1a96c

    auto lambda = [&n]
    {
        std::cout << "in lambda " << &n << std::endl;
    };

    // Here we do an explicit convertion to std::function
    std::cout << "explicit convertion" << std::endl;
    auto function = std::function<void()>{ lambda };
    auto pThreadFunction = call(function);
    pThreadFunction->join();
    // -> in lambda 0x7fffd4e1a96c

    // Here we use an implicit convertion to std::function
    std::cout << "implicit convertion" << std::endl;
    auto pThreadLambda = call(lambda);
    pThreadLambda->join();
    // -> in lambda 0

    return 0;
}

1 个答案:

答案 0 :(得分:2)

用于绑定到const引用函数参数的临时构造的生命周期是包含该函数调用的完整表达式,因此您的线程函数引用了悬空引用。

如果可以保证变量的生命周期包含线程的生命周期,那么只应通过引用将变量捕获到线程函数中,就像functionmain中的局部变量一样。 {1}}。

一种替代方法是在构造临时的全表达式中调用join

call(lambda)->join();

另一个更通用的解决方案是在线程函数中按值捕获functor