I've noticed that when I use std::shared_ptr (or any other smart pointer) a custom allocator/deleter is assigned through the ctor, which happens to be a template. My question is: how is the allocator/deleter stored and used?
Are these functors stored as a function pointer, void*, or what? Is it an indirect call, or a direct call?
Just to have more of a clear understanding of what I'm trying to ask, consider the following code:
struct SomethingAwesomeDeleter
{
public:
void operator()(SomethingAwesome* ptr) const
{
// do something awesome
delete ptr;
}
};
typedef std::shared_ptr<SomethingAwesome> SomethingAwesomePtr;
SomethingAwesomePtr ptr{new SomethingAwesome, SomethingAwesomeDeleter{}};
How is SomethingAwesomeDeleter{} stored and used?
NOTE:
I do realise std::shared_ptr is a template class, however std::shared_ptr does not have template arguments for the deleter/allocator in the class template arguments, i.e. there is no such template class as std::shared_ptr<T, Allocator, Deleter>.
You can store any function object in a std::function. This takes care of either storing the function pointer directly (if it is a plain function) or wrapping it inside some object. That's one possible way to implement a shared_ptr deleter without having the function type being part of the template type.
Example (untested, just to give you the idea)
// This is the struct which actually holds the shared pointer
// A shared_ptr would reference count this
template <typename T>
class shared_ptr_shared
{
std::function<void (T*)> del_;
T* p_;
// other members
template <typename Deleter>
shared_ptr_shared (T* obj, Deleter deleter)
: p_ (p)
, del_ (deleter)
{
}
~shared_ptr_shared ()
{
if (del_) {
del_ (p_);
} else {
delete p_;
}
}
};
You can find out more about std::function does this here: how boost::function and boost::bind work
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