Предотвращение косвенных циклических ссылок при использовании shared_ptr и weak_ptr

Я в настоящее время соединяю приложение, которое полагается в большой степени на shared_ptr и все выглядит хорошим до сих пор - я сделал свою домашнюю работу и имею довольно хорошую идею некоторых ловушек использования shared_ptrs.

Одна из самых распознанных проблем с shared_ptr циклические зависимости - эти проблемы могут быть решены путем хранения weak_ptrs, которые не влияют на время жизни объектов цепочка. Однако я изо всех сил пытаюсь получить голову во времена, где необходимо сохранить указатель на внешний объект через a weak_ptr - Я не уверен, запрещается ли это, препятствуется, или безопасно ли это.

Следующая схема описывает то, что я имею в виду (указывают черные стрелки shared_ptr; подчеркнутый штриховой линией указывают weak_ptr):

сопроводительный текст http://img694.imageshack.us/img694/6628/sharedweakptr.png

  • Родитель содержит shared_ptrs двум детям, оба из которых указывают назад на родителя с помощью a weak_ptr.
  • В конструкторе первого ребенка я получаю через родителя weak_ptr указатель на второго ребенка и хранилище это локально.

Код похож на это:

#include 
#include 
#include 
#include 

class child;
class child2;
class parent;

class parent : public boost::enable_shared_from_this
{
public:
    void createChildren()
    {
        _child2 = boost::make_shared(shared_from_this());
        _child = boost::make_shared(shared_from_this());
    }

    boost::shared_ptr _child;
    boost::shared_ptr _child2;
};

class child
{
public:
    child(boost::weak_ptr p)
    {
        _parent = p;
        _child2 = boost::shared_ptr(p)->_child2; // is this safe?
    }

    boost::weak_ptr _parent;
    boost::shared_ptr _child2;
};

class child2
{
public:
    child2(boost::weak_ptr p)
    {
        this->_parent = p;
    }

    boost::weak_ptr _parent;
};

int main()
{
    boost::shared_ptr master(boost::make_shared());
    master->createChildren();
}

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

7
задан Community 23 May 2017 в 12:24
поделиться

2 ответа

Детский конструктор выглядит безопасно так, как вы его называете. Однако в целом он небезопасен.

Проблема заключается в передаче в качестве аргумента в дочернем конструкторе weak_ptr. Это означает, что вы должны беспокоиться о том, является ли слабый указатель для объекта, который не существует длиннее. Изменяя этот параметр на shared_ptrs и конвертируя его в weak_ptr при хранении, мы знаем, что объект все еще существует. Вот изменение:

child(boost::shared_ptr<parent> p)
{
    _parent = p;
    _child2 = p->_child2; // This is this safe
}
6
ответ дан 7 December 2019 в 03:15
поделиться

Вы получите исключение bad_weak_ptr, если 'p' был (как-то) уже уничтожен. Так что это безопасно, если дочерний ctor ожидает исключений и не безопасно в противном случае.

0
ответ дан 7 December 2019 в 03:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: