Take the following example
struct A {
int x = 0;
};
struct B {
std::shared_ptr<A> mA;
void setA(std::shared_ptr<A> a) {
mA = a;
}
};
struct C {
B initB() {
A a;
A *aPtr = &a;
B b;
b.setA(std::make_shared<A>(aPtr));
return b;
}
};
Now in main()
method
C c;
B b = c.initB();
Local variable a
in initB()
goes out of scope one function finishes executing. However there is a shared pointer pointing to it. Will the object the shared pointer points get deleted when a goes out of scope?
Finally will *(b.mA)
give a valid instance of A
?
Firstly, this doesn't compile.
B initB() {
A a;
A* aPtr = &a;
B b;
b.setA(std::make_shared<A>(/*aPtr*/a););
return b;
}
You have to pass the actual object being made shared, not a pointer to it. Now, to find out the answer to this problem, we can write notifiers for each function, and add constructors and destructors so we can see what is happening.
#include <memory>
#include <iostream>
struct A {
int x = 0;
A() {
std::cout << "A's CTOR" << std::endl;
}
~A() {
std::cout << "A's DTOR" << std::endl;
}
};
struct B {
B() {
std::cout << "B's CTOR" << std::endl;
}
~B() {
std::cout << "B's DTOR" << std::endl;
}
std::shared_ptr<A> mA;
void setA(std::shared_ptr<A> a) {
std::cout << "Entering setA()" << std::endl;
mA = a;
std::cout << "Exiting setA()" << std::endl;
}
};
struct C {
C() {
std::cout << "C's CTOR" << std::endl;
}
~C() {
std::cout << "C's DTOR" << std::endl;
}
B initB() {
std::cout << "Entering initB()" << std::endl;
A a;
A* aPtr = &a;
B b;
b.setA(std::make_shared<A>(/*aPtr*/a));
std::cout << "Exiting initB()" << std::endl;
return b;
}
};
int main() {
std::cout << "Entering Main" << std::endl;
C c;
B b = c.initB();
std::cout << "Exiting Main" << std::endl;
return 0;
}
The output:
Entering Main
C's CTOR
Entering initB()
A's CTOR
B's CTOR
Entering setA()
Exiting setA()
Exiting initB()
B's DTOR
A's DTOR
Exiting Main
B's DTOR
A's DTOR
C's DTOR
Interesting, did you catch what happened? There are 2 A's DTOR
s. std::make_share<A>(a)
actually makes a copy of a
and then makes a shared_ptr
to a
. Since we didn't define a copy assignment operator/constructor, the compiler automatically makes one, and that is why we only have one A's CTOR
. So even though I can't imagine a place where you would do this, it will have a valid instance of A.