Я в настоящее время соединяю приложение, которое полагается в большой степени на shared_ptr
и все выглядит хорошим до сих пор - я сделал свою домашнюю работу и имею довольно хорошую идею некоторых ловушек использования shared_ptr
s.
Одна из самых распознанных проблем с shared_ptr
циклические зависимости - эти проблемы могут быть решены путем хранения weak_ptr
s, которые не влияют на время жизни объектов цепочка. Однако я изо всех сил пытаюсь получить голову во времена, где необходимо сохранить указатель на внешний объект через a weak_ptr
- Я не уверен, запрещается ли это, препятствуется, или безопасно ли это.
Следующая схема описывает то, что я имею в виду (указывают черные стрелки shared_ptr
; подчеркнутый штриховой линией указывают weak_ptr
):
сопроводительный текст http://img694.imageshack.us/img694/6628/sharedweakptr.png
shared_ptr
s двум детям, оба из которых указывают назад на родителя с помощью 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();
}
Я протестировал это, и это, кажется, работает хорошо (я не получаю сообщений об утечках памяти), однако мой вопрос: действительно ли это безопасно? И в противном случае почему нет?
Детский конструктор выглядит безопасно так, как вы его называете. Однако в целом он небезопасен.
Проблема заключается в передаче в качестве аргумента в дочернем конструкторе weak_ptr. Это означает, что вы должны беспокоиться о том, является ли слабый указатель для объекта, который не существует длиннее. Изменяя этот параметр на shared_ptrs и конвертируя его в weak_ptr при хранении, мы знаем, что объект все еще существует. Вот изменение:
child(boost::shared_ptr<parent> p)
{
_parent = p;
_child2 = p->_child2; // This is this safe
}
Вы получите исключение bad_weak_ptr, если 'p' был (как-то) уже уничтожен. Так что это безопасно, если дочерний ctor ожидает исключений и не безопасно в противном случае.