I've been teaching myself the smart pointers that are part of C++0x and came across something that feels inconsistent to me. Specifically, how the destruction policy of unique_ptr<> and shared_ptr<> are handled.
For unique_ptr<>, you can specialize std::default_delete<> and from then on unless you explicitly request a different destruction policy, the new default will be used.
Consider the following:
struct some_c_type;
some_c_type *construct_some_c_type();
void destruct_some_c_type(some_c_type *);
namespace std {
template <> struct default_delete<some_c_type> {
void operator()(some_c_type *ptr) {
destruct_some_c_type(ptr);
}
};
}
Now, once that's in place, unique_ptr<> will use the appropriate destruction policy by default:
// Because of the specialization, this will use destruct_some_c_type
std::unique_ptr<some_c_type> var(construct_some_c_type());
Now compare this to shared_ptr<>. With shared_ptr<>, you need to explicitly request the appropriate destruction policy or it defaults to using operator delete:
// error, will use operator delete
std::shared_ptr<some_c_type> var(construct_some_c_type());
// correct, must explicitly request the destruction policy
std::shared_ptr<some_c_type> var(construct_some_c_type(),
std::default_delete<some_c_type>());
Two questions.
P.S. The reason I care about this is my company does a lot of mixed C and C++ programming. The C++ code often needs to use C-style objects so the ease of specifying a different default destruction policy is quite important to me.
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.
The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.
Afterword. The flawless conversion of an std::unique_ptr to a compatible std::shared_ptr makes it possible to write efficient and safe factory functions. However, note that an std::shared_ptr cannot be converted to an std::unique_ptr.
std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.
I think the question boils down to why std::shared_ptr can have no associated deleter (in which case it just calls delete
) rather than constructing a std::default_delete
by default. (No idea. If the intention was that default_delete
is for specializing, one would expect it to be used by shared_ptr
.)
Otherwise there are trade-offs.
It is better to have fewer template arguments. Boost's reference mentions that this allows a factory to change the allocation scheme without the change affecting the user of the factory.
A unique_ptr
on the other hand is supposed to be very light-weight. How would you store the deleter with zero space overhead (in case of a functor without members) if it wasn't part of the type (GCC uses tuple, where memberless objects don't take memory space)?
Subjectively, I think I'd prefer:
unique_ptr<FILE, FCloser> f(fopen(x, y));
to
unique_ptr<FILE> f(fopen(x, y)); //default_delete<FILE> has been specialized
In the first case there's nothing to guess. If the resource does not come from new
or new[]
, a deleter has to be explicitly given.
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