Question:
I have a C++ program using std::shared_ptr
and std::weak_ptr
involving two classes, A
and B
. The program creates shared pointers for both classes and sets up a relationship between them, with A
holding a weak pointer to B
, and B
holding a shared pointer to A
. According to my understanding, the destructors should be called in the reverse order of the stack calls. However, the output indicates that B
's destructor is called before A
's, which seems unusual to me.
Here is the code snippet:
#include <iostream>
#include <memory>
class B;
class A {
public:
std::weak_ptr<B> b_weak_ptr;
~A() {
std::cout << "A destructor called" << std::endl;
}
};
class B {
public:
std::shared_ptr<A> a_ptr;
~B() {
std::cout << "B destructor called" << std::endl;
}
};
int main() {
{
std::shared_ptr<B> b = std::make_shared<B>();
std::shared_ptr<A> a = std::make_shared<A>();
a->b_weak_ptr = b;
b->a_ptr = a;
}
return 0;
}
Output:
B destructor called
A destructor called
Can anyone explain why the destructor for B
is being called before the destructor for A
?
I initially suspected compiler optimizations might be affecting the order of destructor calls, but checks indicated otherwise.
a
is destroyed first, but that only reduces the reference count to the A
instance by one. There is still one reference to it in b.a_ptr
so the A
instance is not destroyed. When b
is later destroyed (and a_ptr
with it), the reference count to the A
instance becomes zero, and then A
s destructor is called.
A small modification of your code to show it more clearly:
int main() {
std::shared_ptr<B> b = std::make_shared<B>();
{
std::shared_ptr<A> a = std::make_shared<A>();
a->b_weak_ptr = b;
b->a_ptr = a;
std::cout << b->a_ptr.use_count() << '\n'; // prints 2
} // a is destroyed
std::cout << b->a_ptr.use_count() << '\n'; // prints 1
} // b is destroyed
Output:
2
1
B destructor called
A destructor called