сделать shared_ptr не использовать delete - PullRequest
41 голосов
/ 14 января 2009

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

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

Ответы [ 4 ]

56 голосов
/ 14 января 2009

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

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) );
37 голосов
/ 14 января 2009

Вы можете задать шаблон 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), смотрите решение Грега, оно очень хорошее.

10 голосов
/ 14 января 2009

Doug T. ответили на ваш вопрос приятно. Я расскажу вам об 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);
1 голос
/ 14 января 2009

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

Почему бы не заняться очисткой в ​​деструкторе? Даже если это включает deleteMe () в деструкторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...