Reputation: 165
Can someone explain why is the destructor of class bar
being called in the line where the object of the same type is being initialized?
#include <memory>
#include <iostream>
using namespace std;
class bar
{
public:
bar() {}
~bar() { std::cout << "destructor called " << std::endl; }
};
class foo
{
public:
foo(std::shared_ptr<bar> barP) {}
};
int main() {
std::shared_ptr<foo> f;
std::cout << "before init " << std::endl;
f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
std::cout << "after init" << std::endl;
}
Output:
before init
destructor called
after init
Upvotes: 1
Views: 533
Reputation: 2464
First of all, you should not instantiate shared_ptr
in this way, use make_shared
to instantiate shared_ptr
. Please check the modified code -
#include <memory>
#include <iostream>
using namespace std;
class bar
{
public:
bar() {}
~bar() { std::cout << "destructor called " << std::endl; }
};
class foo
{
public:
foo(std::shared_ptr<bar> barP) {}
};
int main() {
std::shared_ptr<foo> f;
std::cout << "before init " << std::endl;
std::shared_ptr<bar> b = std::make_shared<bar>();
f = std::make_shared<foo>(b);
std::cout << "after init" << std::endl;
}
The output of the above program -
before init
after init
destructor called
Generally, what is happening with your code is you are passing new bar
to the constructor of foo
. And no one is holding the ownership of bar
shared pointer. So, the ref count is becoming 0 and it is being deleted, hence the destructor is being called.
Further Read: make_shared vs new
Upvotes: 0
Reputation: 25388
This statement:
f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
constructs a temporary shared_ptr
which goes out of scope at the end of the statement. At that point, the shared_ptr
goes away, taking bar
with it (since no copies of the shared_ptr
remain alive).
But if you change foo
to read like this:
class foo
{
public:
foo(std::shared_ptr<bar> barP) { m_bar = barP; }
std::shared_ptr<bar> m_bar;
};
Then the output you get is probably what you were expecting, because foo
maintains a copy of the shared_ptr
until it (foo
) goes out of scope and that copy keeps bar
alive:
before init
after init
destructor called
Upvotes: 4
Reputation: 7010
It's because the bar
instance only lives as long as the duration of the foo
constructor. So it gets constructed, passed into the shared_ptr
, which is then into the foo
constructor. As soon as that constructor is done (even if on the same line) the expression itself is done, and so the shared_ptr
is done, and destructs.
At the end of main
right before the cout
, you still have a shared_ptr
to foo in f
, but the unnamed shared_ptr
to your bar
object has already gone "out of scope".
Upvotes: 1