Make shared_ptr не использовать delete

в моем коде мне бы хотелось, чтобы boost:: shared_ptr не вызывал delete, а вызывал вместо него ptr- > deleteMe().

Также у меня есть несколько функций стиля C, которые возвращают ptr. Могу ли я заставить его вызвать lib_freeXYZ (ptr); вместо того, чтобы пытаться удалить?

Ответ 1

Или как насчет использования stl для предоставления функтора оболочки - описания Doug T., но без пользовательского вызывающего.

boost::shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );
boost::shared_ptr<S> ptr( new S, std::ptr_fun(lib_freeXYZ) );

Ответ 2

Вы можете предоставить шаблону shared_ptr пользовательскую функцию делетера, которая имеет подпись

  void Deleter( T* ptr);

для boost:: shared_ptr

Итак, для Deleter вы бы сделали

  boost::shared_ptr<T> ptrToT( new T, Deleter );

то в теле Deleter:

   void Deleter( T* ptr);
   {
        ptr->deleteMe();
        // And make sure YOU ACTUALLY DELETE (or do whatever else you need to
        // do to release the resource)
        delete ptr;
   }

Для вашего конкретного случая, когда вам нужно что-то простое (например, ptr- > deleteMe), см. решение Greg, это очень приятно.

Ответ 3

Дуг Т. хорошо ответил на ваш вопрос. Я расскажу вам об intrusive_ptr. Возможно, вы также можете использовать его в своем проекте.

Если у вас есть библиотека C, у которой уже есть подсчет ссылок, но вы должны вручную вызвать эти функции, вы также можете использовать boost::intrusive_ptr и предоставить правильные определения для своих функций add_ref и release. intrusive_ptr найдет и вызовет их. Они несут ответственность за увеличение счетчика ссылок и уменьшение его, освобождая ресурс при необходимости:

void intrusive_ptr_add_ref(foo *f) {
    lib_add_ref(f);
}

void intrusive_ptr_release(foo *f) {
    if(lib_dec_ref(f) == 0) 
        lib_free(f);
}

Затем вы можете просто создавать объекты из необработанных указателей типа foo*. intrusive_ptr будет вызывать ваши функции при его копировании/уничтожении:

intrusive_ptr<foo> f(lib_alloc());

// can wrap raw pointers too, which already may be referenced somewhere else
foo *p = get_foo_from_somewhere();
function_taking_intrusive_ptr(p);

Ответ 4

Для данных стиля С, сделайте как @Doug. T предложил.

Для вашего класса, почему бы не очистить деструктор? Даже если это включает deleteMe() в деструкторе.