在C ++ 11中测试线程时,我创建了以下示例:
#include <iostream>
#include <thread>
class Foo {
public:
Foo(void) {
std::cout << "Constructor called: " << this << std::endl;
}
~Foo(void) {
std::cout << "Destructor called: " << this << std::endl;
}
void operator()() const {
std::cout << "Operatior called: " << this << std::endl;
}
};
void test_normal(void) {
std::cout << "====> Standard example:" << std::endl;
Foo f;
}
void test_thread(void) {
std::cout << "====> Thread example:" << std::endl;
Foo f;
std::thread t(f);
t.detach();
}
int main(int argc, char **argv)
{
test_normal();
test_thread();
for(;;);
}
打印以下内容:
为什么析构函数为线程调用了6次?为什么线程会报告不同的内存位置?
修改 添加移动和复制构造函数输出时:
答案 0 :(得分:6)
将移动或复制功能对象。您没有在输出中考虑任何这些。
答案 1 :(得分:3)
添加复制构造函数并将构造函数移动到您的类中。
Foo(Foo const&) { std::cout << "Copy Constructor called: " << this << std::endl; }
Foo(Foo&&) { std::cout << "Move Constructor called: " << this << std::endl; }
现在如果你运行code输出(在gcc 4.7.2上)看起来像这样:
====> Standard example:
Constructor called: 0xbff696ff
Destructor called: 0xbff696ff
====> Thread example:
Constructor called: 0xbff696ff
Copy Constructor called: 0xbff696cf
Move Constructor called: 0x93a8dfc
Destructor called: 0xbff696cf
Destructor called: 0xbff696ff
Operator called: 0x93a8dfc
Destructor called: 0x93a8dfc
正如您所看到的,对析构函数的调用次数与对各种构造函数的调用次数相匹配。
我怀疑gcc设法忽略了MSVC似乎正在制作的一些复制/移动构造调用,因此对析构函数的调用少于您的示例。
此外,您可以通过std::move
Foo
对象到线程构造函数来完全避免复制构造。
在test_thread
中将线程构造线更改为
std::thread t(std::move(f));
现在输出如下:
====> Standard example:
Constructor called: 0xbfc23e2f
Destructor called: 0xbfc23e2f
====> Thread example:
Constructor called: 0xbfc23e2f
Move Constructor called: 0xbfc23dff
Move Constructor called: 0x9185dfc
Destructor called: 0xbfc23dff
Destructor called: 0xbfc23e2f
Operator called: 0x9185dfc
Destructor called: 0x9185dfc
答案 2 :(得分:2)
因为你的Foo在堆栈上,而不是堆。这意味着你在test_thread中分配一个新的,然后在你调用std :: thread(f)并再次在线程(f)内部时复制它。
您需要创建一个指向堆上的分配的指针,然后传递它,以便每次都不会复制该对象,使用堆(新)来分配它。
答案 3 :(得分:1)
编译器添加默认的移动和复制构造函数,如果你不自己这样做,请检查
#include <iostream>
#include <thread>
class Foo {
public:
Foo(Foo&& f) {
std::cout << "Constructor Foo&& called: " << this << std::endl;
}
Foo(const Foo& f) {
std::cout << "Constructor const Foo& called: " << this << std::endl;
}
Foo(void) {
std::cout << "Constructor called: " << this << std::endl;
}
~Foo(void) {
std::cout << "Destructor called: " << this << std::endl;
}
void operator()() const {
std::cout << "Operatior called: " << this << std::endl;
}
};
void test_normal(void) {
std::cout << "====> Standard example:" << std::endl;
Foo f;
}
void test_thread(void) {
std::cout << "====> Thread example:" << std::endl;
Foo f;
std::thread t(f);
t.detach();
}
int main(int argc, char **argv)
{
test_normal();
test_thread();
for(;;);
}
它显示所有ctors与dtors配对。
另外看看这个SO: