任何人都可以从boost :: thread解释这个意想不到的结果吗?

时间:2015-02-08 22:29:08

标签: c++ c++11 boost boost-thread

考虑针对boost v1.53构建的以下程序。我希望z = 10作为输出,但程序会打印z = -1294967296。任何人都可以解释原因吗?

// g++ -std=c++11 -O2 -Wall -pedantic -lboost_system -lboost_thread main.cpp && ./a.out
#include <iostream>
#include <iomanip>
#include <boost/thread.hpp> // boost v1.53

struct S {
    boost::packaged_task<void> task;
    boost::thread th;
    void async_start(int z) {
        auto worker = [=]() {
            boost::this_thread::sleep_for(boost::chrono::seconds{1});
            std::cout << "z = " << z << '\n' << std::flush; // does not z have the same value as the async_start arg?
        };
        task = boost::packaged_task<void>{worker}; // is not 'worker' copied?
        th = boost::thread{std::move(task)}; // start
    }
};

int main() {
    S s;
    s.async_start(10);
    boost::this_thread::sleep_for(boost::chrono::seconds{3}); // wait some time to make the thread finish
    s.th.join();
}

// z = -1294967296

1 个答案:

答案 0 :(得分:3)

这似乎是Boost bug 8596,已在Boost 1.54中修复。

简单地说,在C ++ 11模式下,boost::packaged_task的构造函数在传递左值时会被破坏,存储引用(!)而不是副本。仿函数由转发引用获取,这意味着当传递左值时,模板参数被推导为左值引用。代码显然忽略了剥离参考性。

作为确认,将prvalue传递给packaged_task的构造函数(直接使用lambda表达式)fixes the problem

    task = boost::packaged_task<void>{[=]() {
        boost::this_thread::sleep_for(boost::chrono::seconds{1});
        std::cout << "z = " << z << '\n' << std::flush;
    }}; 

so does passing an xvalue使用std::move(worker)