A colleague at work was recently tasked with refactoring some legacy code and came across the good old std::auto_ptr
. In C++0x, it has been deprecated (and later removed outright; I can’t even compile std::auto_ptr
code in Visual Studio 2017 nor Xcode 10.1) so it was his job to rewrite it in the modern C++ way. The code that my colleague came across had another problem. Can you spot it?
std::auto_ptr<T> p1(new T[3]);
std::auto_ptr
was never meant to hold pointers to arrays. So the code above, assuming it didn’t crash, was leaking memory (regardless of what it holds, std::auto_ptr
always calls delete
in its destructor; delete[]
was needed in the code above).
So how do we refactor legacy std::auto_ptr
code into modern C++? The answer is std::unique_ptr
(https://en.cppreference.com/w/cpp/memory/unique_ptr). A std::auto_ptr
holding a pointer to a single object of type T
, in modern C++, becomes:
auto p2 = std::make_unique<T>();
std::make_unique
can forward constructor parameters to T::T
, like this:
auto p3 = std::make_unique<T>("string parameter");
And an array of T
s of size N
becomes:
auto p4 = std::make_unique<T[]>(N);
Note that for std::make_unique
to be able to create an array of T
s, T
must have a T::T()
(default constructor; or a constructor with all parameters having default values: T::T(int x = 0)
).