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

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

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

4 ответа

Решение

Или как насчет использования 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) );

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

  void Deleter( T* ptr);

для повышения::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), смотрите решение Грега, это очень приятно.

Дуг Т. приятно ответил на ваш вопрос. Я расскажу вам о 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);

Для данных в стиле C сделайте как @Doug. Т предложил.

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

Другие вопросы по тегам