任何人都可以解释 boost::thread 的这个意外结果吗?
Can anybody explain this unexpected result from 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
的构造函数在传递左值时被破坏,存储引用 (!) 而不是副本。仿函数通过转发引用获取,这意味着当传递左值时,模板参数被推导为左值引用。代码显然忽略了删除引用。
作为确认,将纯右值传递给 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)
.
考虑以下针对 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
的构造函数在传递左值时被破坏,存储引用 (!) 而不是副本。仿函数通过转发引用获取,这意味着当传递左值时,模板参数被推导为左值引用。代码显然忽略了删除引用。
作为确认,将纯右值传递给 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)
.