std :: shared_ptr`循环依赖关系如何导致问题

时间:2019-11-02 20:44:56

标签: c++ c++11 memory-management smart-pointers

我找到了几个相关的问题,但是找不到关于“如何”发生的解释。

我有以下代码,比可以创建循环shared_ptr参考问题的版本落后了一步。 (在返回之前添加b.other = a;会导致问题)

为了更好地进行说明,我在重要的行上添加了注释,以指示此时的程序状态。

#include <iostream>
#include <memory>

using namespace std;

struct Foo
{
    explicit Foo(char i) : id{i} { cout << "Constructed " << id << endl; }
    ~Foo() { cout << "Destructed " << id << endl; }

    shared_ptr<Foo> other = {};
    char const id;
};

int main()
{
    auto const a = make_shared<Foo>('a'); // a_use_count = 1, b_use_count = 0
    auto const b = make_shared<Foo>('b'); // a_use_count = 1, b_use_count = 1

    a->other = b; // a_use_count = 1, b_use_count = 2

    return 0;     // What happens now? Following is my "expectation" (which is wrong !)
                  // 1. destruct b => a_use_count = 1, b_use_count = 1
                  // 2. destruct a (in following order)
                  //    2.1 destruct a.other => b_use_count = 0 => show "Destructed b"
                  //    2.2 destruct a       => a_use_count = 0 => show "Destructed a"
}

但是,事情没有发生我所期望的。 ab的破坏顺序相反。我看到以下输出。

Constructed a
Constructed b
Destructed a
Destructed b

当程序返回到上面时,究竟发生了什么? (我希望了解这一点有助于理解周期性依赖问题)

1 个答案:

答案 0 :(得分:4)

析构函数主体在成员被销毁之前被执行(与构造函数行为相反)。

因此,当a中的main被销毁时,a的共享指针计数首先达到零, ,然后是托管的{{1} }被调用, first 首先放置消息Foo,然后 then Destructed a被销毁,这导致other被打印在托管Destructed b的析构函数。