If a c resource is managed via unique_ptr then does the destructor of the class need to free the heap memory it allocated or it gets free automatically when the unique_ptr goes out of scope? For eg. In below example if I plan to create a unique_ptr to Entity class and I don't add delete in destructor then what will happen?
class Entity
{
private:
int* data;
public:
explicit Entity(const int size) { data = new int[size]; } // acquire
~Entity() { delete[] data; } // release
void do_something() {}
};
void functionUsingEntity() {
Entity e(100); // lifetime automatically tied to enclosing scope
e.do_something();
} // automatic destruction and deallocation for e
CodePudding user response:
int* data;
This is a pointer. When a pointer is destroyed, nothing happens to whatever it points to. If it is a last pointer to a dynamic allocation when it's destroyed, then that allocation will leak.
explicit Entity(const int size) { data = new int[size]; } // acquire ^^^^^^^^^^^^^^
Here, you allocate a dynamic array. If you don't deallocate it using delete[]
, then it will leak.
If a c resource is managed via unique_ptr then does the destructor of the class need to free the heap memory it allocated or it gets free automatically when the unique_ptr goes out of scope?
If a resource is owned by std::unique_ptr
, then the destructor of std::unique_ptr
will delete the resource. The dynamic array that you allocated is not owned by a std::unique_ptr
. In order for it to be owned by a std::unique_ptr
, you must change the type of the member to be a std::unique_ptr
.
In below example if I plan to create a unique_ptr to Entity class and I don't add delete in destructor then what will happen?
Then the allocation that is not owned by a unique pointer will leak.
~Entity() { delete[] data; } // release
This is an incomplete attempt at implementing the RAII pattern. In order for deletion in the destructor to be correct, you must first ensure that the pointer is unique. That isn't currently enforced because your copy/move constructors and copy/move assignment operators make a copy of the pointer. Using any of those will result in undefined behaviour. You should follow the rule of 5 if you delete anything in the destructor.
Or, a better design would be to use an existing RAII class such as a smart pointer or a container i.e. follow the rule of 0:
class Entity
{
private:
std::unique_ptr<int[]> data;
public:
explicit Entity(const int size) : data(std::make_unique<int[]>(size)) {}
CodePudding user response:
When you create a std::unique_ptr<Entity> ptr
to class Entity
, and when ptr
goes out of scope, it invokes the destructor of the class Entity
. Now, if class Entity
allocates any memory(as in this case) or is holding other resources, it is the responsibility of the destructor of class Entity
to free the memory and release the resources. If you don't free the memory in the destructor, your application will end-up leaking memory.