Как циклическая зависимость `std :: shared_ptr` вызывает проблему - PullRequest
2 голосов
/ 02 ноября 2019

Я нашел несколько связанных вопросов, но не смог найти объяснения относительно того, «как» это происходит.

У меня есть следующий код, который на один шаг позади версии, которая может создать циклический 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"
}

Однако, вещине случилось, как я ожидаю. a и b уничтожаются в обратном порядке. Я вижу следующий вывод:

Constructed a
Constructed b
Destructed a
Destructed b

Что именно происходит, когда программа возвращается выше? (Я надеюсь, что понимание этого поможет понять проблему циклической зависимости)

1 Ответ

4 голосов
/ 02 ноября 2019

Тело деструктора выполняется до , члены уничтожаются (обратное поведение конструктора.)

Поэтому, когда a в main уничтожается, счетчик общего указателяa достигает нуля сначала , затем вызывается деструктор управляемого Foo, сначала , выводящий сообщение Destructed a, и затем other уничтожается, что приводит к печати Destructed b в деструкторе управляемого им Foo.

...