Is it true that unique_ptr which points to an array will automatically free dynamic memory after calling release()?

I looked a little in this, and I'm guessing this was just a mistake on the author's part. cppreference.com makes no reference to any array specialization for release. Just to make sure, I went ahead and checked the source code for libc++ (LLVM's implementation of the standard library). This is the implementation for std::unique_ptr<T[], Deleter>::release. As you can see, it does not call delete[]. My guess is the author meant to write up.reset();, as this does free the memory.


// up points to an array of ten uninitialized ints
unique_ptr<int[]> up(new int[10]);
up.release();   // automatically uses delete[] to destroy its pointer

This is incorrect. up.release() is not calling delete[] for the array it manages. It is simply releasing ownership of the array and returning a pointer to it. It is, therefore, the responsibility of the coder to call delete[].

I think you are getting mixed up with std::unique_ptr<T, Deleter>::reset() which does free the allocated memory.

Demo:

#include <iostream>
#include <memory>

class Test
{
public:
    Test() { std::cout << "Test()" << std::endl; }
    ~Test() { std::cout << "~Test()" << std::endl; }
};

int main()
{
    std::unique_ptr<Test[]> up(new Test[3]);
    auto ptr = up.release();

    return 0;
}

Output:

Test()
Test()
Test()

The destructor is not called. So we have a memory leak! The only way to avoid this is to call delete[] ptr; after auto ptr = up.release();

Note: from C++14 onward you can write:

std::unique_ptr<CTest[]> up = std::make_unique<CTest[]>(3);

This is better than explicitly new-ing because it will not leak if an exception is thrown.

Tags:

C++

Unique Ptr