So no, you shouldn't. The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.
A null shared_ptr does serve the same purpose as a raw null pointer. It might indicate the non-availability of data. However, for the most part, there is no reason for a null shared_ptr to possess a control block or a managed nullptr .
Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.
Pointer to Managed Object (or Managed Object) A control block contains a pointer to the managed object, which is used for deleting the object. One interesting fact is that the managed pointer in the control block could be different in type (and even value) from the raw pointer in the shared_ptr.
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) );
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. 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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With