Destructor for Dynamic Array in C++
- Understanding Dynamic Arrays in C++
- Destructor for Dynamic Array in C++
- Example of Destructor in C++
- Delete Dynamic Array Using Destructor in C++
- Pitfalls and Best Practices
- Conclusion
While programming in any programming language, we often hear about constructors and destructors. Constructors are special member functions used to initialize the object of a class, whereas destructors are also special functions that are automatically called when an object is going to be destroyed.
In C++, a dynamic array, often referred to as a resizable array or a vector, is a versatile data structure that dynamically allocates memory to accommodate a varying number of elements. Understanding and implementing a destructor for such a dynamic array is crucial to managing memory properly and preventing memory leaks.
This article will discuss the destructor for dynamic arrays in C++ in detail.
Understanding Dynamic Arrays in C++
Dynamic arrays in C++ are typically implemented using pointers to a block of memory, which can be resized as needed to accommodate changing data sizes. The new
and delete[]
operators are used to allocate and deallocate memory for these arrays, respectively.
Here’s a simple example of a dynamic array implementation:
class DynamicArray {
private:
int* arr;
int size;
public:
// Constructor
DynamicArray(int initialSize) {
size = initialSize;
arr = new int[size];
}
// Destructor
~DynamicArray() { delete[] arr; }
// Other methods for manipulation (add, remove, access elements, etc.)
};
The DynamicArray
class manages a dynamically allocated array of integers. It uses a constructor to initialize the size of the array and dynamically allocate memory for it using new
and a destructor to ensure that memory is properly deallocated using delete[]
when the object is destroyed, preventing memory leaks.
Additional methods can be added to perform various operations on the array stored within this class.
The Role of Destructors
A destructor in C++ is a special member function that is automatically called when an object goes out of scope or is explicitly deleted. Its primary purpose is to release any resources (like memory, file handles, etc.) that the object might have acquired during its lifetime.
For a dynamic array, the destructor plays a crucial role in preventing memory leaks by deallocating the memory that was allocated using new
. If the destructor is not properly implemented, the memory allocated for the dynamic array will not be freed when the object is destroyed, leading to memory leaks.
In the example provided earlier, the destructor ~DynamicArray()
uses the delete[]
operator to release the memory allocated for the dynamic array arr
. This ensures that when an object of DynamicArray
goes out of scope or is explicitly deleted, the memory used by the array is properly deallocated.
It’s essential to note that if the dynamic array contains elements that were themselves dynamically allocated (like objects created using new
), the destructor should handle releasing memory for those elements as well. This may involve iterating through the array and deleting individual elements before deallocating the array itself.
Destructor for Dynamic Array in C++
Destructors are special member functions that have the same name as the class and are automatically invoked when an object is going to be destroyed.
The destructor function is the last function that is called when an object is destroyed. It cleans up the memory that the objects created by the constructor occupy.
However, both the constructor and destructor have the same name as that of the class, but there lies a difference between the two in terms of how they are written so that the compiler can differentiate them. The destructors are written using a negation symbol (~
) followed by the class name and the constructors with just the class name.
Moreover, there can only be a single destructor for a class, but the constructors can be multiple.
Whenever an object is created in C++, it occupies memory in the heap section, and we use the new
keyword to dynamically create that object of the class. Similarly, the delete
keyword is used to delete the dynamically created object of the class.
Need for Destructor in C++
We need to delete the object to avoid any memory leaks. A memory leak occurs when the programmers forget to delete the memory in the heap that is not in use.
Because of this, the computer’s performance reduces as it reduces the amount of available memory. Moreover, if the objects are not explicitly deleted using the destructors, the program will crash during the runtime.
Example of Destructor in C++
In this example, we will be dynamically creating the object of a class using the new
operator and explicitly deleting it using the delete
keyword in C++.
Below is an example of how to delete the object of a class using the delete
operator in C++.
#include <iostream>
using namespace std;
class Employee {
public:
Employee() { cout << "Constructor of Employee class was called!\n"; }
~Employee() { cout << "Destructor of Employee class was called!\n"; }
void work() { cout << "Still Working!\n"; }
};
int main() {
Employee* emp = new Employee();
emp->work();
delete emp;
return 0;
}
Output:
Constructor of Employee class was called!
Still Working!
Destructor of Employee class was called!
In the above example, we have made a class Employee
with a constructor, destructor, and a work
function containing the appropriate message about their actions.
In the main
function, we have created the object of the class emp
using the new
keyword and have called the work()
function with it. After which, we just used the delete
operator and the object name emp
to delete the same.
Delete Dynamic Array Using Destructor in C++
Until now, we have seen how to delete a single object of a class using the delete
keyword in C++. Now, let us see how to delete a dynamic array or an array of objects in C++.
In this example, we will create a dynamic array in C++ using the new
keyword and then delete it using the delete
operator.
However, one thing to remember while deleting a dynamic array in C++ is that we have to use the delete []
operator for doing so and not just delete
. Therefore, the delete
operator is used to delete a single object of a class, whereas to delete a dynamic array or an array of objects, we have to use the delete []
operator in C++.
Now, let us understand it with the help of a code example.
#include <iostream>
using namespace std;
class Employee {
public:
Employee() { cout << "Constructor of Employee class was called!\n"; }
~Employee() { cout << "Destructor of Employee class was called!\n"; }
void work() { cout << "Still working!\n"; }
};
int main() {
Employee* emp = new Employee[3];
emp[0].work();
emp[1].work();
emp[2].work();
delete[] emp;
return 0;
}
Output:
Constructor of Employee class was called!
Constructor of Employee class was called!
Constructor of Employee class was called!
Still working!
Still working!
Still working!
Destructor of Employee class was called!
Destructor of Employee class was called!
Destructor of Employee class was called!
In this code example, we have a similar code as the previous example, but this time, we have created three Employee
objects and deleted them using the delete []
operator in C++.
However, if we use the delete
operator instead of the delete []
, the program crashes during runtime. Let us also see an example of that to understand the deletion of the dynamic array in C++ more clearly.
#include <iostream>
using namespace std;
class Employee {
public:
Employee() { cout << "Constructor of Employee class was called!\n"; }
~Employee() { cout << "Destructor of Employee class was called!\n"; }
void work() { cout << "Still working!\n"; }
};
int main() {
Employee* emp = new Employee[3];
emp[0].work();
emp[1].work();
emp[2].work();
delete emp;
return 0;
}
Output:
Error in `./example1.cpp': munmap_chunk(): invalid pointer: 0x000000000117f018 ***
timeout: the monitored command dumped core
/bin/bash: line 1: 33 Aborted timeout 15s ./0f6c05b9-ee09-44c3-acee-8ad8a882ac5e < 0f6c05b9-ee09-44c3-acee-8ad8a882ac5e.in
Constructor of Employee class was called!
Constructor of Employee class was called!
Constructor of Employee class was called!
Still working!
Still working!
Still working!
Destructor of Employee class was called!
Therefore, as you can see in the above output, the constructors and the function work
have been called for all three objects, but the destructor has only been called once for a single object, after which the program crashed.
Pitfalls and Best Practices
When dealing with destructors for dynamic arrays, several pitfalls must be avoided:
- Double Deletion: Ensure that the memory deallocation occurs only once. Deleting the same memory block multiple times can lead to runtime errors.
- Memory Leak Prevention: If the dynamic array contains pointers to allocated memory, those pointers should be properly managed within the destructor to avoid memory leaks.
- Copy and Move Constructors/Assignment Operators: When implementing these functions for your class, ensure proper memory allocation and deallocation to avoid shallow copying issues that might impact the destructor’s functionality.
Conclusion
In conclusion, understanding the role of constructors and destructors in managing dynamic arrays in C++ is essential for effective memory management and preventing memory leaks. Constructors initialize the dynamic array, while destructors ensure proper deallocation of memory when the object goes out of scope.
The destructor for a dynamic array is crucial as it releases the memory allocated using new
, preventing memory leaks. It’s vital to implement the destructor correctly, especially if the array contains dynamically allocated elements, to handle their deallocation as well.
Remembering to use delete[]
for dynamic arrays and avoiding double deletion is crucial for proper memory management. Additionally, when implementing copy and move constructors or assignment operators, ensure they handle memory allocation and deallocation correctly to avoid issues impacting the destructor’s functionality.
By understanding and implementing proper memory management techniques, programmers can ensure efficient and reliable handling of dynamic arrays in C++, enhancing program stability and performance.
Related Article - C++ Array
- Associative Arrays in C++
- How to Represent the Deck of Cards in C++ Array
- How to Deallocate a 2D Array in C++
- Array of Arrays in C++
- How to Check if an Array Contains an Element in C++