shared_ptr, подписка, деструктор - PullRequest
2 голосов
/ 18 декабря 2009

Я использую указатели Boost / shared_ptr во всем приложении. Когда будет выпущена последняя ссылка на объект, shared_ptr удалит этот объект для меня. Объекты в приложении подписываются на события в центральном местоположении приложения, аналогично схеме наблюдателя / подписчика.

В деструкторах объекта он сам отписывается от списка подписок. Список подписок по сути просто list<weak_ptr<MyObject> >. Я хочу сделать что-то похожее на это:

Type::~Type()
{
  Subscriptions::Instance()->Remove(shared_from_this());
}

Моя проблема здесь в том, что shared_from_this нельзя вызывать в деструкторах, поэтому приведенный выше код вызовет исключение.

В моей старой реализации список подписки был просто списком указателей, и затем он работал. Но вместо этого я хочу использовать слабые ссылки, чтобы уменьшить риск испортить память при ручном управлении памятью.

Так как я полагаюсь на shared_ptr для удаления объектов, в моем коде нет ни одного места, где я мог бы логически сделать вызов Unsubscribe.

Есть идеи, что делать в этой ситуации?

Ответы [ 2 ]

1 голос
/ 18 декабря 2009
  1. Вы можете уничтожить объекты с помощью экземпляра подписки, тогда он автоматически удалит указатели.
  2. Вы можете забыть об удалении их из подписок - в любом случае, слабый_портер не сможет быть заблокирован, тогда вы можете удалить их.
  3. Вы можете назначить уникальный идентификатор каждому объекту, а затем удалить с помощью уникального идентификатора, а не shared_ptr
  4. Вы можете передать обычный указатель на удаление вместо общего - он будет служить «идентификатором».
0 голосов
/ 13 декабря 2018

Моя проблема в том, что shared_from_this нельзя вызвать в деструкторы, поэтому приведенный выше код будет выдавать исключение.

Будет выброшено исключение , поскольку срок его действия истек по определению в деструкторе.

Так что же вы хотите? Общий указатель с истекшим сроком действия? Просто создайте пустой общий указатель.

Или слабый указатель с истекшим сроком действия?

Возможно, если вы заметите, что «проблема» не в shared_from_this броске (это симптом), а в том, что все владельцы уже изначально сброшены или уничтожены в этой точке, а срок действия слабых указателей истек и эквивалент к пустому стандартному слабому указателю (*), созданному по умолчанию, поэтому вам нужно просто передать инициализированный слабый указатель по умолчанию.

Также Subscriptions::Instance()->Remove(weak_OR_owning_pointer) не имеет смысла в любом случае (со слабым или владеющим указателем), так как вы не можете сравнить слабый указатель с чем-либо, вы можете только попытаться заблокировать его (а затем выполнить сравнение).

Так что вы можете просто удалить устаревшие слабые указатели. Аргументы Remove бесполезны.

(*) или что у вас есть очень серьезная двойная ошибка двойного владения уничтожаемым объектом!

...