41

in my code i would like boost::shared_ptr not to call delete but call ptr->deleteMe() instead.

Also i have a few C styled functions that return a ptr. Can i make it call lib_freeXYZ(ptr); instead of trying to delete?

4 Answers4

56

Or how about using the stl to provide the wrapper functor - Doug T. description but without the custom caller.

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) );
Greg Domjan
  • 13,943
  • 6
  • 43
  • 59
  • 3
    I actually prefer this, more elegant. – Doug T. Jan 15 '09 at 12:11
  • I needed some clarifications so I added another question: http://stackoverflow.com/questions/27962978/boost-smart-pointer-with-custom-deleter. Thanks! – Liviu Jan 15 '15 at 12:05
37

You can give the shared_ptr template a custom deleter function which has the signature

  void Deleter( T* ptr);

for a boost::shared_ptr

So for Deleter you would do

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

then in the body of 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;
   }

For your specific case when you need something simple (like ptr->deleteMe) see Greg's solution, its very nice.

Doug T.
  • 64,223
  • 27
  • 138
  • 202
  • 1
    i had a similar case where i had to prevent shared_ptr to call delete - it was because the object was allocated statically. may be interesting: http://stackoverflow.com/questions/363453/looking-for-a-better-c-class-factory#363543 – Johannes Schaub - litb Jan 14 '09 at 00:36
  • It may be necessary to make sure `ptr != 0` before dereferencing it in the deleter. At least I have found that to be the case using std::tr1::shared_ptr on gcc 4.4.5. – Brent Bradburn Feb 20 '13 at 19:21
  • The additional call to `delete ptr` is a bit confusing here -- it's like you want to delete the object twice (first with `ptr->deleteMe()`). I think normally you would use a deleter because you want to do something _instead of_ `delete ptr`, not _in addition to_. – Brent Bradburn Feb 20 '13 at 19:25
  • You have an extra semicolon in the "body of Deleter" section of code. (`void Deleter( T* ptr);` <-- here ) – Cory Jul 17 '15 at 18:29
10

Doug T. answered your question nicely. I'll tell you about intrusive_ptr. Maybe you can use it in your project too.

If you have some C library that has already reference counting, but you have to manually call those functions, you can use boost::intrusive_ptr too, and provide proper definitions for its add_ref and release functions. intrusive_ptr will find and call them. They are responsible to increment the reference count and decrement it, freeing the resource when necassary:

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);
}

Then you can just create objects from raw pointers of type foo*. intrusive_ptr will call your functions when its copied/destructed:

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);
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
1

For the C-style data, do as @Doug. T suggested.

For your class, why not do cleanup in a destructor? Even if this is including deleteMe() in the destructor.

Kris Kumler
  • 6,307
  • 3
  • 24
  • 27
  • Perhaps there are some boundary issues? calling delete in a different module could be bad, especially if it is using a different crt instance. – Greg Domjan Jan 14 '09 at 00:13
  • Indeed. In that case, an overloaded delete operator? – Kris Kumler Jan 14 '09 at 00:24
  • Kris - why is Doug answer preferred over Greg answer? Personally, I like the syntax in Greg's answer (especially because I'm dealing with a C library that has a free function for the pointer it returns). But I have no idea about the technical merits or differences. – jww Feb 23 '14 at 01:10
  • @noloader -- I would prefer Greg's. This one was posted before he created the answer though... – Kris Kumler Feb 25 '14 at 02:23