Reputation: 458
I am curious why a simple c++ program like the one attached below calls destructor of the work1 object multiple times while it is being processed in std::thread. Why is that it calls destructor multiple times.
class work1 {
public:
work1(int x_) : x(x_) {
++count;
std::cout<<"\n[WORKER1] Ctor : "<<count<<std::endl;
}
~work1() {
std::cout<<"\n[WORKER1] Dtor : "<<count<<std::endl;
}
void operator() () {
for(int i =0; i < x; ++i) {
std::cout<<"[WORKER1] Printing this :: "<<i<<std::endl;
}
}
private:
int x;
static int count;
};
int main()
{
int local_main=5;
std::thread t((work1(local_main)));
t.join();
std::cout<<"\n[MAIN] From main thread..."<<std::endl;
return 0;
}
The above code produces the following output:
[WORKER1] Ctor : 1
[WORKER1] Dtor : 1
[WORKER1] Dtor : 1
[WORKER1] Printing this :: 0
[WORKER1] Printing this :: 1
[WORKER1] Printing this :: 2
[WORKER1] Printing this :: 3
[WORKER1] Printing this :: 4
[WORKER1] Dtor : 1
[MAIN] From main thread...
Upvotes: 0
Views: 187
Reputation: 136208
std::thread
makes a copy of the argument by calling the copy constructor. Implement the copy constructor to observe the copies:
class work1 {
public:
work1(int x_) : x(x_) {
++count;
std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
}
work1(work1 const& other)
: x(other.x)
{
++count;
std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
}
work1& operator=(work1 const& other)
{
x = other.x;
std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
return *this;
}
~work1() {
--count;
std::cout << __PRETTY_FUNCTION__ << ' ' << count << '\n';
}
void operator() () {
for(int i =0; i < x; ++i) {
std::cout<<"[WORKER1] Printing this :: "<<i<<std::endl;
}
}
private:
int x;
static int count;
};
int work1::count;
int main() {
int local_main=5;
std::thread t((work1(local_main)));
t.join();
}
Outputs:
work1::work1(int) 1
work1::work1(const work1&) 2
work1::work1(const work1&) 3
work1::~work1() 2
work1::~work1() 1
[WORKER1] Printing this :: 0
[WORKER1] Printing this :: 1
[WORKER1] Printing this :: 2
[WORKER1] Printing this :: 3
[WORKER1] Printing this :: 4
work1::~work1() 0
If you'd like to avoid copying pass a reference to your functional object the thread using std::ref
:
int main() {
work1 w{5};
std::thread t(std::ref(w));
t.join();
}
Outputs:
work1::work1(int) 1
[WORKER1] Printing this :: 0
[WORKER1] Printing this :: 1
[WORKER1] Printing this :: 2
[WORKER1] Printing this :: 3
[WORKER1] Printing this :: 4
work1::~work1() 0
Upvotes: 1