Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

unique-ptr

As far as I know, calling std::unique_ptr<T,Deleter>::release only transfers ownerships, won't free the dynamic memory.

From C++ Primer 5th:

p2.release(); // WRONG: p2 won't free the memory and we've lost the pointer
auto p = p2.release(); // ok, but we must remember to delete(p)

But after a few pages it writes:

The library provides a version of unique_ptr that can manage arrays allocated by new. To use a unique_ptr to manage a dynamic array, we must include a pair of empty brackets after the object type:

// 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

The brackets in the type specifier (<int[]>) say that up points not to an int but to an array of ints. Because up points to an array, when up destroys the pointer it manages, it will automatically use delete[].


So is it true that std::unique_ptr<T,Deleter>::releas treats dynamically allocated array differently, which is freeing the allocated memory automatically after calling release()? If it's true, then it also indicates that one can't transfer ownership of an dynamic array. I couldn't find any authoritative references on the Web so far.

like image 314
Rick Avatar asked Dec 11 '19 05:12

Rick


People also ask

Does unique_ptr delete automatically?

That is, you should know that a unique_ptr will safely delete its underlying raw pointer once it goes out of scope.

What does unique_ptr get do?

unique_ptr::getReturns a pointer to the managed object or nullptr if no object is owned.

What does unique_ptr Reset do?

unique_ptr::resetReplaces the managed object. 1) Given current_ptr , the pointer that was managed by *this, performs the following actions, in this order: Saves a copy of the current pointer old_ptr = current_ptr. Overwrites the current pointer with the argument current_ptr = ptr.

What happens when you move a unique_ptr?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because multiple ownership adds complexity to the program logic.


2 Answers

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.

like image 77
LRFLEW Avatar answered Nov 15 '22 06:11

LRFLEW


// 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.

like image 38
jignatius Avatar answered Nov 15 '22 06:11

jignatius