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

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

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


person Community    schedule 13.01.2009    source источник


Ответы (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) );
person Greg Domjan    schedule 14.01.2009
comment
Я вообще-то предпочитаю этот, более элегантный. - person Doug T.; 15.01.2009
comment
Мне потребовались некоторые пояснения, поэтому я добавил еще один вопрос: stackoverflow.com/questions/27962978/. Спасибо! - person Liviu; 15.01.2015

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

person Doug T.    schedule 13.01.2009
comment
У меня был аналогичный случай, когда мне пришлось запретить shared_ptr вызывать delete - это было потому, что объект был выделен статически. может быть интересно: stackoverflow.com/questions/363453/ - person Johannes Schaub - litb; 14.01.2009
comment
Может потребоваться убедиться ptr != 0 перед разыменованием его в средстве удаления. По крайней мере, я обнаружил, что это так, используя std :: tr1 :: shared_ptr в gcc 4.4.5. - person Brent Bradburn; 20.02.2013
comment
Дополнительный вызов delete ptr здесь немного сбивает с толку - это как если бы вы хотите удалить объект дважды (сначала с ptr->deleteMe()). Я думаю, что обычно вы использовали бы удаление, потому что вы хотите сделать что-то вместо delete ptr, а не в дополнение к. - person Brent Bradburn; 20.02.2013
comment
У вас есть лишняя точка с запятой в теле раздела кода Deleter. (void Deleter( T* ptr); ‹- здесь) - person Cory; 17.07.2015

Дуг Т. хорошо ответил на ваш вопрос. Расскажу про 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);
person Johannes Schaub - litb    schedule 14.01.2009

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

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

person Kris Kumler    schedule 13.01.2009
comment
Возможно, есть какие-то проблемы с границами? вызов delete в другом модуле может быть плохим, особенно если он использует другой экземпляр crt. - person Greg Domjan; 14.01.2009
comment
Верно. В таком случае перегруженный оператор удаления? - person Kris Kumler; 14.01.2009
comment
Крис - почему ответ Дуга предпочтительнее ответа Грега? Лично мне нравится синтаксис в ответе Грега (особенно потому, что я имею дело с библиотекой C, в которой есть бесплатная функция для возвращаемого указателя). Но я понятия не имею о технических достоинствах или различиях. - person jww; 23.02.2014
comment
@noloader - я бы предпочел Грега. Этот был опубликован до того, как он создал ответ ... - person Kris Kumler; 25.02.2014