Как разорвать циклическую ссылку shared_ptr с помощью weak_ptr
Я читал, что уязвимые_поинтеры могут использоваться для разрыва циклических ссылок
Рассмотрим следующий пример циклической ссылки
struct A
{
boost::shared_ptr<A> shrd_ptr;
};
boost::shared_ptr<A> ptr_A(boost::make_shared<A>());
boost::shared_ptr<A> ptr_b(boost::make_shared<A>());
ptr_A->shrd_ptr = ptr_b;
ptr_b->shrd_ptr = ptr_A;
Теперь выше приведен случай циклической ссылки, и я хотел знать, как можно разорвать циклическую ссылку выше с помощью weak_ptr
?
Обновление: на основании полученного предложения я придумал следующее:
struct A
{
boost::weak_ptr<A> wk_ptr;
};
boost::shared_ptr<A> ptr_A (boost::make_shared<A>());
boost::shared_ptr<A> ptr_B (boost::make_shared<A>());
ptr_A->wk_ptr = ptr_B;
ptr_B->wk_ptr = ptr_A;
Будет ли это правильный подход?
1 ответ
Классический пример циклических ссылок, где у вас есть два класса A
а также B
где A
имеет ссылку на B
который имеет ссылку на A
:
#include <memory>
#include <iostream>
struct B;
struct A {
std::shared_ptr<B> b;
~A() { std::cout << "~A()\n"; }
};
struct B {
std::shared_ptr<A> a;
~B() { std::cout << "~B()\n"; }
};
void useAnB() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b = b;
b->a = a;
}
int main() {
useAnB();
std::cout << "Finished using A and B\n";
}
Если обе ссылки shared_ptr
тогда это говорит A
владеет B
а также B
владеет A
, который должен звонить в колокола. Другими словами, A
держит B
жив и B
держит A
в живых.
В этом примере экземпляры a
а также b
используются только в useAnB()
функция, поэтому мы хотели бы, чтобы они были уничтожены, когда функция заканчивается, но, как мы видим, когда мы запускаем программу, деструкторы не вызываются.
Решение состоит в том, чтобы решить, кто кому принадлежит. Допустим A
владеет B
но B
не владеет A
тогда мы заменим ссылку на A
в B
с weak_ptr
вот так:
struct B {
std::weak_ptr<A> a;
~B() { std::cout << "~B()\n"; }
};
Тогда, если мы запустим программу, мы увидим, что a
а также b
уничтожены, как мы ожидаем.
Редактировать: в вашем случае предложенный вами подход выглядит вполне обоснованным. Отнимите собственность от A
и что-то еще владеет A
s.