Arrays, shared_ptr< T >s, and deleters
In my last few posts about shared_ptr<T>s I’ve been using a struct called private_deleter. When you first attach a target object to a shared_ptr<T> you can also specify a deleter, which is a functor with an operator() that takes a single argument, a pointer to the target object, and deletes it.
// Instances of some_type will be managed
// with shared_ptr< some_type >s.
struct
some_type
{ };
// Deleter that works when you create
// some_type with operator new.
struct
some_type_deleter
{ void
operator ()( some_type * p)
{ delete p; }
};
// This shared_ptr has no deleter, so the
// target is deleted with the function
// boost::checked_delete< some_type >(..).
shared_ptr< some_type >
sp_1(
new some_type);
// Boost provides a standard deleter struct
// that calls boost::checked_delete<T>(..).
shared_ptr< some_type >
sp_2(
new some_type,
boost::checked_deleter< some_type >( ));
// This target object is bound to a new instance
// of our deleter struct, defined above.
shared_ptr< some_type >
sp_3(
new some_type,
some_type_deleter( ));
You use the deleter, of course, to control target object deletion. Which is symmetric since you also control target creation. Without the deleter you could only create target objects with operator new to match the operator delete assumed by shared_ptr.
Since the deleter becomes part of the intermediate object (aka the “control block”), you can also use it as a way to add variables and functions without intruding on the target class. For example, you can use it to store a list of notifier functors to be triggered when the target is deleted. Or you can use it as a chunk of memory in which you construct the target object. But in this post we’re just going to use the deleter to delete.
The Boost smart pointers provide a shared pointer just for arrays, called shared_array<T>. It is similar to shared_ptr<T> except it uses operator delete[] instead of operator delete to delete the target. But shared_array<T> is not part of TR1, and it is not necessary since shared_ptr<T> supports custom deleters.
The following shows how to use a deleter so shared_ptr<T> correctly deletes arrays.
# include <boost/detail/lightweight_test.hpp>
# include <boost/shared_ptr.hpp>
using boost::shared_ptr;
// Deleter to correctly delete arrays
// (remember it's OK to delete a const)
template< typename T >
struct
array_deleter
{
void
operator ()( T const * p)
{ delete[] p; }
};
// Example target object
struct
my_type
{ my_type( ) { balance += 1; }
~my_type( ) { balance -= 1; }
static int balance;
};
int my_type::balance = 0;
int
main( )
{
// Create an array and bind it to an array_deleter
// with shared_ptr. The my_type constructor is
// called 7 times, followed by 7 calls to the
// destructor.
{ shared_ptr< my_type >
sp_array(
new my_type[ 7 ],
array_deleter< my_type >( ));
}
BOOST_TEST( 0 == my_type::balance);
return boost::report_errors( );
}
Boost even provides an array-deleter class (checked_array_deleter<T>) so you don’t have to define one yourself.
# include <boost/shared_ptr.hpp> using boost::shared_ptr; using boost::checked_array_deleter; shared_ptr< my_type > sp_array_inst( new my_type[ 53 ], checked_array_deleter< my_type >( ));
Since shared_array<T> is no longer necessary to support array deletion, I suspect it will never become part of the standard library. operator [] is not enough justification for its existence. It will languish in the Boost library, a barely supported dead-end experiment, and will never be integrated with shared_ptr and weak_ptr.
As a final note, another way to work with arrays and shared_ptrs is to use an array wrapper like the TR1 array class. Since you can allocate these objects with operator new you can rely on the default shared_ptr deleter.
# include <boost/array.hpp> using boost::array; shared_ptr< array< my_type, 4 > > sp_array2( new array< my_type, 4 >);
But shared_ptr< array< my_type, 4 > > is a lot more awkward than simple shared_ptr< my_type >, and I doubt it will become a common idiom.
Comments
One Response to “Arrays, shared_ptr< T >s, and deleters”
Leave a Reply
[...] Mehr Spannendes zum Thema shared_ptr und Arrays findet sich hier: shared_ptr bei MSDN Arrays, shared_ptr and deleters shared_ptr und c-Arrays shared_ptr Tutorial Diskussion auf Stackoverflow Wer mit dem Code [...]