Yes, it's safe. If this was not safe, then std::shared_ptr
would be pretty useless.
"b" which is an instance of B will be released at the end of function foo.
Yes, but its std::shared_ptr<A>
is copied before that.
Let's look at what the last line of the function really does:
return b.get_a();
get_a()
produces a std::shared_ptr<A>
, which is copied to a temporary object. This temporary std::shared_ptr<A>
object is then copied again to become the result of the call in main
.
(Actual copies may even be elided due to return-value optimisation, but that doesn't change anything. If anything, it makes the safety even easier to understand.)
Only then is b
destroyed, but the std::shared_ptr<A>
in it has already been copied by that time.
The std::shared_ptr<A>
instance within b
is destroyed, too, but the memory for the A
object is not freed. That's the whole point of std::shared_ptr
-- it knows how often it was copied and frees dynamically allocated memory only when the last copy is destroyed.
"a" in the main function is a shared_ptr of B::m_a.
No. It's a std::shared_ptr<A>
, but that's it. It has nothing to do with the original B::m_a
anymore.
Is it safe to use "a" after "b" is released?
Yes, because there is no lasting relationship between a
and b
.
Basically, you are questioning the safety a fundamental feature of C++, namely returning values from functions. Returning a std::shared_ptr
is not different with regards to safety than returning a std::string
or an int
. That's always what happens when you return by value from a function: The to-be-returned value is copied, the original is destroyed, the copy lives on.