As far as I understand the smart pointers, they are there to avoid memory leaks among other things. However there are often objects which also need to be released, but not by
You can construct both shared_ptr
(signature #3 here) and unique_ptr
(signature #2 here) with custom deleters.
using T = ...;
auto deleter = [](T* x) { delete x; };
// different deleter - different unique_ptr type
// deleter is stored inline
auto x = std::unique_ptr<T, decltype(deleter)>(new T(...), deleter);
// same shared_ptr<T> type regardless of the deleter type,
// deleter is stored in the "shared state"
auto y = std::shared_ptr<T>(new T(...), deleter);
Note, make_shared()
cannot be used to construct a shared_ptr
with custom deleter.
Both shared_ptr
and unique_ptr
provide that facility.
For shared_ptr
, the constructor is a template:
An optional deleter d can be supplied that is later used to destroy the object when no shared_ptr objects own it. By default, a delete-expression for type Y is used as the deleter.
In this case, the deleter can be any callable, copy-constructible value, which get type-erased to the callable.
For unique_ptr
, the type of the deleter is a type parameter of the pointer itself:
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
There's no erasure in this case, and the deleter provided to the c-tor or the reset actually matches the deleter type.
If you are using unique_ptr
or shared_ptr
, you can provide your custom deleter. The deleter for a unique_ptr
is passed as a template parameter, and
Deleter must be FunctionObject or lvalue reference to a FunctionObject or lvalue reference to function, callable with an argument of type
unique_ptr<T, Deleter>::pointer
For the shated_ptr
, the deleter should be provided as the constructor parameter.
class Foo
{
};
class Deleter
{
public:
void operator()(Foo *)
{
std::cout << "deleter";
}
};
int main() {
std::unique_ptr<Foo, Deleter> ptr(new Foo());
std::shared_ptr<Foo> ptr1(new Foo(),
[](Foo*){std::cout << "deleter for shared_ptr";}
);
}
You have to be careful not to cause memory leaks, though.