Since raw pointers have very few reasons for existence in modern C++, std::unique_ptr, powered by RAII, is a frequent guest in our codebase. But the power of RAII doesn’t stop at pointers and std::unique_ptr can be used to manage any unique resources. It’s fairly easy - std::unique_ptr just needs to know how to dispose of the resource once it’s no longer needed. That’s where deleter comes into the picture
So unique pointer calls it in its destructor. Sounds reasonable. So how does it look in practice? Let’s say that for some reason we need to use std::FILE. They are usually created using std::fopen and closed using std::fclose, but it’s easy to end up in a situation where std::fclose is not invoked - forgotten branch, exception or lack of protocol knowledge. That’s what std::unique_ptr can help with. There are 3 common ways to achieve this:
using a lambda (ptr)
using a functor class (ptr2)
using a function
Functor class works great but requires some boilerplate code. static assert indicates that the size of such pointer is 8 bytes, which is expected for a 64bit OS. Somewhat surprisingly, passing a deleter function results in 16 byte pointer size! But why? The answer boils down to the fact that when we use a Deleter class, unique_ptr can instantiate it in its destructor and call its instance, so pointer doesn’t need any extra fields to store state. In case of a deleter function, unique pointer has to store the pointer to its address, so that it can be accessed in unique_ptr destructor.
So are we stuck with boilerplate to avoid size increase? Fortunately, not! Lambdas combine concise syntax and functor size efficiency, which should be expected since it’s essentially a syntactic sugar for functor classes.