为什么实例化一个 shared_ptr 调用析构函数?

Why instantiating a shared_ptr calling destructor?

谁能解释一下为什么class bar 的析构函数在同类型对象初始化的那一行被调用?

    #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;
    }

输出:

before init 
destructor called 
after init

首先,你不应该这样实例化shared_ptr,使用make_shared来实例化shared_ptr。请检查修改后的代码 -

#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;
}

以上程序的输出-

before init 
after init
destructor called 

通常,您的代码正在将 new bar 传递给 foo 的构造函数。并且没有人持有 bar 共享指针的所有权。因此,引用计数变为 0 并被删除,因此正在调用析构函数。

进一步阅读make_shared vs new

这是因为 bar 实例仅在 foo 构造函数的持续时间内存在。所以它被构造,传递到 shared_ptr,然后传递到 foo 构造函数。一旦该构造函数完成(即使在同一行),表达式本身也完成,因此 shared_ptr 完成,并析构。

main 的末尾 cout 之前,您仍然有一个 shared_ptrf 中的 foo,但是未命名的 shared_ptr您的 bar 对象已经消失 "out of scope".

这条语句:

f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

构造一个临时的 shared_ptr ,它在语句末尾超出范围。在那一点上,shared_ptr 消失了,带走了 bar(因为没有 shared_ptr 的副本仍然存在)。

但是如果你把foo改成这样:

class foo
{
  public:
    foo(std::shared_ptr<bar> barP) { m_bar = barP; }
    std::shared_ptr<bar> m_bar;
};

那么您得到的输出可能就是您所期望的,因为 foo 维护着 shared_ptr 的副本,直到它 (foo) 超出范围并且该副本保留bar 活着:

before init 
after init
destructor called

Live demo