Reputation: 7435
I found several related questions, but I couldn't find an explanation regarding "how" this happens.
I have the following code, which is one step behind the version that can create a cyclic shared_ptr
reference problem.
(Adding b.other = a;
before return causes the problem)
For better clarification, I added comments on important lines to indicate the state of the program at that point.
#include <iostream>
#include <memory>
using namespace std;
struct Foo
{
explicit Foo(char i) : id{i} { cout << "Constructed " << id << endl; }
~Foo() { cout << "Destructed " << id << endl; }
shared_ptr<Foo> other = {};
char const id;
};
int main()
{
auto const a = make_shared<Foo>('a'); // a_use_count = 1, b_use_count = 0
auto const b = make_shared<Foo>('b'); // a_use_count = 1, b_use_count = 1
a->other = b; // a_use_count = 1, b_use_count = 2
return 0; // What happens now? Following is my "expectation" (which is wrong !)
// 1. destruct b => a_use_count = 1, b_use_count = 1
// 2. destruct a (in following order)
// 2.1 destruct a.other => b_use_count = 0 => show "Destructed b"
// 2.2 destruct a => a_use_count = 0 => show "Destructed a"
}
However, things do not happen as I expect. a
and b
gets destructed in the opposite order. I am seeing the following output.
Constructed a
Constructed b
Destructed a
Destructed b
What exactly happens when the program returns above? (I hope understanding this will help understanding the cyclic dependency problem)
Upvotes: 2
Views: 119
Reputation: 22152
The destructor body is executed before the members are destroyed (the reverse of the constructor behavior.)
Therefore when a
in main
is destructed, the shared pointer count of a
reaches zero first, then the destructor of the managed Foo
is called, first prining the message Destructed a
, and then other
is destroyed, which causes Destructed b
to be printed in the destructor of its managed Foo
.
Upvotes: 4