在以下代码中:
在Windows上使用
#include <iostream>
#include <thread>
using namespace std;
class tester {
public:
tester() {
cout << "constructor\t" << this << "\n";
}
tester(const tester& other) {
cout << "copy cons.\t" << this << "\n";
}
~tester() {
cout << "destructor\t" << this << "\n";
}
void print() const {
cout << "print\t\t" << this << "\n";
}
};
int main() {
tester t;
cout << " before lambda\n";
thread t2([=] {
cout << " thread start\n";
t.print();
cout << " thread end\n";
});
t2.join();
cout << " after join" << endl;
return 0;
}
在Windows上使用
cl.exe
编译时,我得到以下结果:constructor 012FFA93
before lambda
copy cons. 012FFA92
copy cons. 014F6318
destructor 012FFA92
thread start
print 014F6318
thread end
destructor 014F6318
after join
destructor 012FFA93
使用WSL上的g++
编译器,我获得以下结果:
constructor 0x7ffff5b2155e
before lambda
copy cons. 0x7ffff5b2155f
copy cons. 0x7ffff5b21517
copy cons. 0x7fffedc630c8
destructor 0x7ffff5b21517
destructor 0x7ffff5b2155f
thread start
print 0x7fffedc630c8
thread end
destructor 0x7fffedc630c8
after join
destructor 0x7ffff5b2155e
我希望
[=]
捕获会创建恰好1个tester
的副本。为什么会有多个立即被销毁的副本?为什么MSVC和GCC存在差异?这是未定义行为还是其他原因?
std::thread
必须以某种方式存储 lambda 表达式,这可能涉及复制。我相信闭包 可以 移动其捕获的对象,但是由于您的类型没有提供移动构造函数,因此在可以移动而不是复制的情况下,它被强制复制。如果您添加一个移动构造函数,那么您可能会看到较少的复制。 - François Andrieux