c++ - 任何人都可以解释 boost::thread 的这个意外结果吗?

标签 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

最佳答案

这似乎是 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)

关于c++ - 任何人都可以解释 boost::thread 的这个意外结果吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28400120/

相关文章:

c++ - 对 C++ 11 可变模板参数进行操作,存储到元组中

c++ - 检测给定类型是否为 C++03 中的函数类型

c++ - 如何在 CentOS 8 docker 上安装 gcc/g++ 9 (centos :latest)

c++ - 调整列表列大小时 HDN_ENDTRACK 出现问题

c++ - 在 C++ 中,嵌套 vector 消耗大量内存

C++11构造函数继承和纯虚方法

c++ - 本地类的限定名称

c++ - 在命名空间中对自己的类使用 boost::program_options::validate

c++ - Boost Geometry 中用户定义的空间谓词

performance - 随机数,C++11 与 Boost