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?
1 |
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:
1 |
auto p2 = std::make_unique<T>(); |
std::make_unique can forward constructor parameters to T::T, like this:
1 |
auto p3 = std::make_unique<T>("string parameter"); |
And an array of T’s of size N becomes:
1 |
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)).
Should we use container or std::array for dynamic array ? I think it’s better than warping pointer to an array with smart pointer . 🙂