c++11 - 通过引用捕获时如何异步使用 C++11 lambda

标签 c++11 asynchronous lambda capture

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

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

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

我正在使用g++-4.9 (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405(实验)[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;
}

最佳答案

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

如果您可以保证变量的生命周期包含线程的生命周期,则应该仅通过引用将变量捕获到线程函数中,正如您在 function 是本地函数的情况下所做的那样main 中的变量。

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

call(lambda)->join();

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

关于c++11 - 通过引用捕获时如何异步使用 C++11 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24283486/

相关文章:

c# - 异步/等待有/没有等待(即发即弃)

javascript - 使用NodeJS在事件池中处理请求

c++ - cpp中 "[=]"是什么意思

c# - 如何验证 lambda 查询是否返回 null

C++11类函数的多重定义

c++ - 是否可以获取 atomic_int 的底层存储地址?

c++ - 了解弱引用计数器

c++ - 复制 MPI_Win?

c# - MVC 3 - 如何在异步 WCF 调用后立即 RedirectToAction

c++ - C++11 中 lambda 的非确定性损坏