How do I destruct a dynamically allocated array of dynamic object? - c++

I write a class vector whose member is a dynamically allocated array
template <typename T> struct vector{
T* elem;int capacity;
/*
*capacity is the size of array, not number of elements in the array .
*the default capacity is 3.
*/
vector(int c=3,T e=0){ /* initializing all elements as e */
T* elem=new T[capacity = c];
for(int i=0;i<capacity;i++){
elem[i]=e;
}
}
~vector(){
delete[] elem;
}
};
Now this is the point, regarding the destructor of vector. If the elements in the member elem is also dynamically allocated object obj, and this object also has its own destructor
int main(){
vector<obj*> vec;
vec.elem[0] = new obj(parameter)
vec.elem[1] = new obj(parameter)
vec.elem[2] = new obj(parameter)
...
}
Is it necessary to delete all the objects in the destructor of vector? like this
~vector(){
for(int i=0;i<capacity;i++){
delete elem[i];
}
delete[] elem;
}
Or I should only delete[] elem and the destructor of obj will finish the rest of work?

Is it necessary to delete all the objects in the destructor of vector? like this
Technically yes but what if you want a vector of pointers that does not represent ownership? You could easily end up either double-deleting an object, or trying to delete a stack-based object:
obj obj_a;
obj* obj_b = new obj;
vector<obj*> obj_ptrs;
obj_ptrs.elem[0] = &obj_a;
obj_ptrs.elem[1] = &obj_a;
obj_ptrs.elem[2] = obj_b;
delete obj_b;
Whether the pointed objects need to be deleted with the vector is none of the vector's business.
The cleanest way to address that is to use std::unique_ptr, which is an object type that holds a pointer and deletes it when it gets destroyed:
#include <memory>
template <typename T> struct vector {
// ...
~vector() {
// The vector is only responsible for deleting the array.
delete[] elem;
}
};
// ...
void foo() {
vector<std::unique_ptr<obj>> obj_ptrs;
obj_ptrs.elem[0] = std::make_unique<obj>();
obj_ptrs.elem[1] = std::make_unique<obj>();
obj_ptrs.elem[2] = std::make_unique<obj>();
obj stack_obj;
vector<obj*> obj_no_own_ptrs;
obj_no_own_ptrs.elem[0] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[1] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[2] = &stack_obj;
// Everything gets deleted
// No double-delete concern
}

In general, when you call delete in an object first it calls the destructor of the class, and second deallocate the memory where the object was allocated.
So, yes. If you create a class call vector it is necessary that you call delete if elem was dynamically allocated before with new.
New always have to be paired with delete. The standard approach was to, e.g. place the new in the constructor, and the delete in the destructor of a class.
In your case, in your class you are dynamically allocating space for other class, that happens to be also a dynamically allocated pointer.
first_object->second_object->third_object...
In this case first_object contain a dynamically allocated vector to second_object. second_object of course can contain more dynamically allocated memory.
In the destructor of your first_object, you delete the second_object so you call the destructor of the second object and deallocate its memory. The call to the destructor of the second_object should delete the third object, so its memory is also deallocated.
If you allocate memory and don't deallocate it, you start to mess the memory because you are fragmenting it. If you call delete without new, or in a object that has been already deleted there will be a segfault. It is always a good idea to place news in constructor and delete in destructors.
Nowadays you also can use shared_ptr or unique_ptr. They will automatically delete its content when they go out scope.
In particular shared_ptr will delete its content when the last pointer pointing to one resource goes out scope
unique_ptr will delete its content when it goes out of scope, since by definition forbid more than one pointer pointing to its content.
{
std::shared_ptr foo = std::make_shared();
std::shared_ptr foo2(new Foo());
}
Both shared pointers will delete its content automatically when they will go out of scope. The first option is preferred and more efficient (make_shared better than call the constructor with new). You could also use unique_ptr that are similar in characteristics to shared_ptr they don't allow more than one pointer pointing to the same resource.
I think you can read about smart pointers and about RAII and it will help you with this

Related

How to choose the adequate, delete or delete[]? [duplicate]

What is the difference between delete and delete[] operators in C++?
The delete operator deallocates memory and calls the destructor for a single object created with new.
The delete [] operator deallocates memory and calls destructors for an array of objects created with new [].
Using delete on a pointer returned by new [] or delete [] on a pointer returned by new results in undefined behavior.
The delete[] operator is used to delete arrays. The delete operator is used to delete non-array objects. It calls operator delete[] and operator delete function respectively to delete the memory that the array or non-array object occupied after (eventually) calling the destructors for the array's elements or the non-array object.
The following shows the relations:
typedef int array_type[1];
// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;
// create and destroy an int
int *b = new int;
delete b;
// create and destroy an int[1]
int *c = new int[1];
delete[] c;
// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;
For the new that creates an array (so, either the new type[] or new applied to an array type construct), the Standard looks for an operator new[] in the array's element type class or in the global scope, and passes the amount of memory requested. It may request more than N * sizeof(ElementType) if it wants (for instance to store the number of elements, so it later when deleting knows how many destructor calls to done). If the class declares an operator new[] that additional to the amount of memory accepts another size_t, that second parameter will receive the number of elements allocated - it may use this for any purpose it wants (debugging, etc...).
For the new that creates a non-array object, it will look for an operator new in the element's class or in the global scope. It passes the amount of memory requested (exactly sizeof(T) always).
For the delete[], it looks into the arrays' element class type and calls their destructors. The operator delete[] function used is the one in the element type's class, or if there is none then in the global scope.
For the delete, if the pointer passed is a base class of the actual object's type, the base class must have a virtual destructor (otherwise, behavior is undefined). If it is not a base class, then the destructor of that class is called, and an operator delete in that class or the global operator delete is used. If a base class was passed, then the actual object type's destructor is called, and the operator delete found in that class is used, or if there is none, a global operator delete is called. If the operator delete in the class has a second parameter of type size_t, it will receive the number of elements to deallocate.
This the basic usage of allocate/DE-allocate pattern in c++
malloc/free, new/delete, new[]/delete[]
We need to use them correspondingly. But I would like to add this particular understanding for the difference between delete and delete[]
1) delete is used to de-allocate memory allocated for single object
2) delete[] is used to de-allocate memory allocated for array of objects
class ABC{}
ABC *ptr = new ABC[100]
when we say new ABC[100], compiler can get the information about how many objects that needs to be allocated(here it is 100) and will call the constructor for each of the objects created
but correspondingly if we simply use delete ptr for this case, compiler will not know how many objects that ptr is pointing to and will end up calling of destructor and deleting memory for only 1 object(leaving the invocation of destructors and deallocation of remaining 99 objects). Hence there will be a memory leak.
so we need to use delete [] ptr in this case.
The operators delete and delete [] are used respectively to destroy the objects created with new and new[], returning to the allocated memory left available to the compiler's memory manager.
Objects created with new must necessarily be destroyed with delete, and that the arrays created with new[] should be deleted with delete[].
When I asked this question, my real question was, "is there a difference between the two? Doesn't the runtime have to keep information about the array size, and so will it not be able to tell which one we mean?" This question does not appear in "related questions", so just to help out those like me, here is the answer to that: "why do we even need the delete[] operator?"
C++ delete[] operator ensures that Destructor for all object allocated with new[] is called. The following example demonstrates the same. Also, delete[] must be preferred (if new[] used previously) when the class has a non-default destructor to release the acquired resources. Otherwise, it might result in memory leaks.
Common Code:-
#include <iostream>
using namespace std;
class memTest{
public:
static int num;
memTest(){
cout<<"Constructor from object " << num++ << endl;
}
~memTest(){
cout<<"Destructor from object " << --num << endl;
}
};
int memTest::num=0;
Example 1:- use of new[] and delete may result in undefined behavior.
int main() {
memTest* Test1=new memTest[3];
delete Test1; //<-----
return 0;
}
Output 1:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2 //<-----
Example 2: The correct behavior is using new[] and delete[].
int main() {
memTest* Test1=new memTest[3];
delete[] Test1; //<-----
return 0;
}
Output 2:-
Constructor from object 0
Constructor from object 1
Constructor from object 2
Destructor from object 2
Destructor from object 1 //<-----
Destructor from object 0 //<-----
delete is used for one single pointer and delete[] is used for deleting an array through a pointer.
This might help you to understand better.

Is it mandatory for destructor to use delete when managed via unique pointer?

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
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)) {}
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.

Difference between destructors in my class

I'm implementing a simplified unique pointer. Everything was pretty clear, but I wonder about the destructor in my class.
Should it be ~unique_pointer(){obj->~T();} or ~unique_pointer(){delete obj}?
I really don't see a difference between these. Can you explain how they work?
Below is the whole class:
template<class T>
class unique_pointer{
private:
T*obj;
public:
unique_pointer(const T* obj):obj{obj}{}
~unique_pointer(){obj->~T();}
T operator*() const { return *obj; }
T* operator->() const { return obj; }
T* release(){
T* temp = obj;
obj = 0;
return obj;
}
};
It should be ~unique_pointer(){obj->~T();} or ~unique_pointer(){delete obj}. I really don't see difference between each other.
obj->~T() destroys the pointed object. If the object is stored in dynamic memory, then the memory is not dealloated. If nothing else deallocates the memory, then the memory is leaked. Given that the point of a unique pointer is to manage dynamic allocation, doing this would be rather pointless.
delete obj If obj was created with allocating new, then this destroys the object and frees the deallocation. Otherwise the behaviour of the program is undefined. This is what std::default_delete, the default deleter of std::unique_ptr, does (unless the template type argument is T[] in which case it calls delete[] instead).
Some simple rules of thumb that apply to most cases:
If you new, then delete
Delete only if you newed
Never delete more than once
If you newed an array, then delete[] instead
Don't use new nor delete except in implementation of a smart pointer or similar low level memory management class
If you malloc, then free
Never free more than once
Don't malloc
If you placement new, then call destructor explicitly
Don't placement new unless you know what you're doing
P.S. Your release doesn't seem to make sense, as it doesn't release obj, has an unused variable temp, and uses some undeclared val.
Furthermore, it is copyable and have undefined behaviour if copied or moved. A unique pointer shouldn't be copyable, and needs a custom definition for move.

C++ Deleting a pointer to a object that contains another pointer

Let's say
class A {
A* array;
public:
A (){
array= new A [4];
}
~A (){
delete array;
}
}
How do we free an object if we create such an object on heap like
A* object_ptr =new A();
I'm a bit confused about freeing a pointer that points to an object containing another pointer.....
Calling
delete object_ptr;
after
A* object_ptr =new A();
will invoke the destructor of the A pointed to by object_ptr. That means, if you fix your wrong
~A (){
delete array;
}
to
~A (){
delete[] array;
}
your code will be fine and the internal pointer is freed correctly.
However, you really should use std::vector instead of new[]. It will make your life a whole lot easier. If you insist on new[], read about The Rule of Three.
Two things to note.
When deleting arrays you should use []. For example: delete [] array;
When deleting pointers the destructor of the allocated object will get called. You would call from your code: delete object_ptr; to delete your pointer.
Another important point to be aware of is what happens when you copy your object. If your object ever gets copies you will have problems where one destructor deletes the pointers out from under another object. This is why shared_ptr is a good alternative to raw pointers (see this question on how to use shared_ptr).

Is it a memory leak to push_back a pointer into a vector of pointers?

In my class, I have a member variable std::vector<node*> children
Does the following class member function create a memory leak?
//adds a child node
{
node* child = new node("blah","blah","blah");
child->Set_Parent(this);
children.push_back(child); //<- Is this ok?
}
The vector makes a copy of the pointer and I have two pointers to the same memory,
and then the original pointer goes out of scope, right?
This may be simple and obvious, but I would just like to confirm my assumption.
thanks
It's not a leak ... yet. However, if the vector goes out of scope, or you erase, pop_back or do something else that removes elements from the vector, without first deleteing the element that you're removing you'll have a leak on your hands.
The right way to do this is to change from using a vector<node *> to vector<unique_ptr<node>>. Your code will change to
//adds a child node
{
node* child = new node("blah","blah","blah");
child->Set_Parent(this);
children.push_back(std::unique_ptr<node>(child));
}
Or use boost::ptr_vector<node> if you can use Boost.
It's only a memory leak if you forget to deallocate the children node when the class containing the vector's destructor is called.
It's not a memory leak. You still have a pointer in the vector and you will be able to free the memory when needed.
When the vector goes out of scope, it's destructor doesn't destroy the pointed-to object. It destroys the pointer -- which does nothing.
Your code created that object via new. Your code is responsible for deleting that object. If you don't do so, you have a leak. If you do so to early, i.e., before removing the pointer from the vector, you have even bigger problems.
Assuming children is a class member you would just simply delete all the items in the vector on the class deconstructor.
struct Foo{};
class Bar
{
public:
Bar(){};
~Bar()
{
for( vector<Foo*>::iterator it = children.begin(); it != children.end(); ++it )
{
SAFE_DELETE( (*it) ); //use your own macro/template or use delete if you don't have one
delete (*it);
(*it) = NULL;
}
}
vector<Foo*>children;
}
Foo* p = new Foo();
children.push_back( p );
If you used a vector<Foo>child instead, every push_back on the vector would create a copy of the original object to be stored, but since you're using pointers, in this case allocated on the heap by new no object copy is created, the pointer that points to a long-life term object is simply stored, meaning yes, you have to delete it later.