цепочка / ответвление shared_ptr со вторым удалителем

#c #boost #shared-ptr

#c #повышение #общий-ptr

Вопрос:

У меня ситуация, когда мне нужно знать, когда пользователь shared_ptr завершен, то есть когда пользователь, наконец, выпустил все его копии. Обычно здесь просто используется удаление, но в этом случае есть небольшая загвоздка. Базовый объект уже является shared_ptr!

То есть в псевдокоде:

 shared_ptr<T> a( new T );
.
.
.
shared_ptr<T> b( a, bind( delete_func, id ) );
  

Я создаю новую ветку из исходного shared_ptr. Этот новый shared_ptr b может быть скопирован и использован как обычный shared_ptr, но функция delete_func должна вызываться при выполнении этой конкретной ветви. Теперь я не могу просто использовать a.get() здесь, поскольку этот новый shared_ptr также должен сохранять базовый объект (это может быть последний shared_ptr для него).

Я ищу какой-то способ сделать это без необходимости кардинально менять структуру. Кто-нибудь видит хорошее простое решение?

Я использую библиотеку boost для интеллектуальных указателей и привязки.

Ответ №1:

Я придумал одно возможное решение.

Создайте функцию удаления следующим образом:

 void delete_func( int id, shared_ptr<T> underlying );
  

Затем, чтобы связать shared_ptr, сделайте это:

 shared_ptr<T> b( a.get(), bind( amp;delete_func, id, a ) );
  

Это создает новый несвязанный shared_ptr с пользовательским удалителем (моя ветвь). Одним из параметров является исходный shared_ptr, поэтому он также должен поддерживать базовый объект shared_ptr. Теперь мне просто нужно немного протестировать это.

Комментарии:

1. Разве это не вызовет удаление, когда последняя копия b выйдет из области видимости. Копии a вполне могут находиться в области видимости в данный момент. — Почему бы просто не добавить пользовательский удалитель a , когда он создается в первую очередь?

2. @visitor, это именно то, что требуется. По сути b , предполагается, что у него есть собственное время жизни, которое по завершении отменяет регистрацию через удалитель.

Ответ №2:

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

Комментарии:

1. Считайте, что a это часть некоторого внутреннего модуля. Вызывается функция, к a которой также требуется доступ, но система должна знать, когда этот внешний вызывающий объект завершит ее использование. Таким образом, он не может вернуться a напрямую, поскольку тогда он никогда не узнает, поэтому каким-то образом он должен подключиться к времени жизни этой новой копии переменной.