为什么我不应该将带有按引用捕获的 lambda 传递给 std::thread 构造函数?

问题描述 投票:0回答:1

我编写了一个计时器类,但它没有按照我需要的方式工作。谁能告诉我这有什么问题吗?

template<typename D, typename C>
class timer
{
public:
    timer(D period, C&& callback)
    {
        std::thread t{[&](){
            std::this_thread::sleep_for(period);
            callback();
        }};

        t.detach();
    }
};

int main()
{
    timer t1(std::chrono::seconds(2), [](){
        std::cout << "hello from 1\n";
    });

    timer t2(std::chrono::seconds(3), [](){
        std::cout << "hello from 2\n";
    });

    std::this_thread::sleep_for(std::chrono::seconds(5));
}

输出只有:

hello from 1

“hello from 2”行在哪里?

c++ c++17
1个回答
4
投票

这里:

timer(D period, C&& callback)
{
    std::thread t{[&](){
        std::this_thread::sleep_for(period);
        callback();
    }};

    t.detach();
}

period

 返回时,
callback
timer
正在被破坏,并且
timer
在调用
callback()
之前返回,甚至可能在调用
sleep_for
之前返回。

解决方法是将

period
callback
复制到线程的函子中,以便这些副本在线程运行时仍然有效:

timer(D period, C&& callback)
{
    std::thread t{[=](){
        std::this_thread::sleep_for(period);
        callback();
    }};

    t.detach();
}
© www.soinside.com 2019 - 2024. All rights reserved.