I have some legacy-era code at work that takes in a double-pointer and allocates memory to it. A shortened example of it would look something like this:
struct LegacyObj { int a; double b; }; void LegacyAllocator(LegacyObj** ppObj) { *ppObj = (LegacyObj*)malloc(sizeof(LegacyObj)); } void LegacyDeleter(LegacyObj** ppObj) { free(*ppObj); } The actual LegacyAllocator function is ~100 lines and mixes reading from files with creating a linked list of LegacyObj pointers, and isn't something I'd be able to get away with rewriting right now. I would like, however, to make the use of this function a bit safer, avoiding any memory leaks that may occur from exceptions &tc. The first solution I came up with was to wrap it up in a class and handle calling the legacy functions in the ctor/dtor.
class RAIIWrapper { public: RAIIWrapper() :obj{nullptr} { ::LegacyAllocator(&obj); } RAIIWrapper(RAIIWrapper&& that) : obj{ that.obj} { that.obj = nullptr; } RAIIWrapper& operator=(RAIIWrapper&& that) { RAIIWrapper copy{std::move(that)}; std::swap(obj, copy.obj); return *this; } ~RAIIWrapper () { ::LegacyDeleter(&obj); } private: LegacyObj* obj; }; But I'm curious - is there a way to do this using std::shared_ptr or std::unique_ptr? I've not been able to come up with a solution without having to keep the original pointer passed to LegacyAllocator around.
unique_ptrandshared_ptrdon't take allocators, they only take deleters. You would allocate the pointer yourself withLegacyAllocator(&obj)and make a deleter functor for theunique_ptr/shared_ptrwhich callsLegacyDeleter(&p)in itsoperator()