I am trying to understand how the shared_ptr
counters work. In my class A
when I used a getter the counter incremented by 1. When used an instance of A
in class B
the counter incremented by 2. When I got Done with class B
the destructor of A
got called twice.
What I didn't understand and what confused me is the following:
Why did the counter of A
increment by 1 when we called the getter a.a()
. Is it because we returned a pointer by Copy so now we have 2 pointers right?
Why do we have a counter of 3 when the desctructor of A
was called?
In class B
why did the counter increment by 2?
After finishing of class B
how was the destructor of A
called?
When I use reset
in the both destructors it gets weirder.
#include <iostream>
#include <memory>
using namespace std;
class A {
public:
A(int a):_a( make_shared<int>(a)) {cout <<"A constructor" << endl;}
~A(){/*_a.reset();*/cout <<"After destructor, number of As "<< _a.use_count() <<endl;}
std::shared_ptr<int> a(){return _a;}
//private:
std::shared_ptr<int> _a;
};
class B {
public:
B(A a):_b( make_shared<A>(a)) {cout <<"B constructor" << endl;}
~B(){ /*_b.reset();*/ cout <<"After destructor, number of Bs "<< _b.use_count() << endl;}
std::shared_ptr<A> b(){return _b;}
private:
std::shared_ptr<A> _b;
};
int main()
{
int number = 10;
A a(number);
cout <<"counter of A is " << a._a.use_count() << endl;
cout <<"counter of A is " << a.a().use_count() << endl;
B b(a);
cout <<"counter of A is " << a.a().use_count() << endl;
cout <<"counter of B is " << b.b().use_count() << endl;
return 0;
}
A--->Number: Counter = 1
B(constructor) pass A by value : counter = 2
B--->Number: Counter = 3
A constructor
counter of A is 1
counter of A is 2
B constructor
After destructor, number of As 3
counter of A is 3
counter of B is 2
After destructor, number of Bs 1
After destructor, number of As 2
After destructor, number of As 1
A constructor
counter of A is 1
counter of A is 2
B constructor
After destructor, number of As 0
counter of A is 3
counter of B is 2
After destructor, number of As 0
After destructor, number of Bs 0
After destructor, number of As 0
a.a()
it returns a new shared pointer to the resources. The first one is the member variable. They are eventually released but there's no quarantees as you don't store the returned shared pointer into a variable (which would bind it to a scope).After destructor, ...
is because you copy value of A a
into constructor of B. If you wish to avoid copy, then use a reference B(A& a)
.A a
internal one, the returned but not released a.a()
result AND the copy of A a
passed to the constructor of B
.b.b()
-> increment counter by one.I hope this covers all of your questions, I can try to clarify further if you have any questions.