【问题标题】:How does `std::shared_ptr` cyclic dependency cause a problem`std::shared_ptr` 循环依赖如何导致问题
【发布时间】:2020-02-28 16:33:37
【问题描述】:

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

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

为了更好地说明,我在重要的行添加了 cmets 以指示当时程序的状态。

#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

当程序返回上面时究竟会发生什么? (我希望理解这一点有助于理解循环依赖问题)

【问题讨论】:

  • 显示的程序发生的事情并不是很复杂,但是它与循环依赖引起的潜在问题几乎无关,除非是非常基本的方式。
  • 这个 Q 是专门针对 C++11 的吗?
  • @curiousguy 这是关于 C++11 及更高版本的,因为 std::shared_ptr 之前不可用。

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


【解决方案1】:

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

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

【讨论】:

  • 谢谢,我忽略了显而易见的事情。我会再考虑一下我是否了解循环依赖问题并接受您的回答或更新我的问题。
  • @Sumudu 如果你想用shared_ptr 演示循环依赖问题,那么你需要实际使依赖循环,例如添加b-&gt;other = a。如果您在这种情况下进行相同的分析,您将看到没有一个析构函数将执行,这表明内存泄漏。
猜你喜欢
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多