When testing threads in C++11 I have created the following example:
#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(;;);
}
Which prints the following:
Why is the destructor called 6 times for the thread? And why does the thread report different memory locations?
EDIT When adding move and copy constructor output:
Add a copy constructor and move constructor to your class.
Foo(Foo const&) { std::cout << "Copy Constructor called: " << this << std::endl; }
Foo(Foo&&) { std::cout << "Move Constructor called: " << this << std::endl; }
Now if you run the code the output (on gcc 4.7.2) looks like this:
====> 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
As you can see, the number of calls to the destructor matches the number of calls to the various constructors.
I suspect gcc manages to elide a few of the copy / move construction calls that MSVC seems to be making, so there are fewer calls to destructor than your example.
Furthermore, you can avoid the copy construction completely by std::move
ing the Foo
object to the thread constructor.
In test_thread
change the thread construction line to
std::thread t(std::move(f));
Now the output looks like this:
====> 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