C++ Memory Management using new and delete operators
One of the key features that makes C++ a powerful language is its ability to manage memory directly. Unlike languages with automatic garbage collection, C++ provides control over memory allocation and deallocation, which is crucial for efficient resource management, especially in performance-critical applications. The two fundamental operators used in C++ memory management are new
and delete
.
new
is used to dynamically allocate memory on the heap.delete
is used to free the dynamically allocated memory when it is no longer needed.In this guide, we will explore how new
and delete
work, along with best practices for memory management in C++.
Dynamic memory allocation refers to the process of allocating memory at runtime (during program execution) instead of at compile time. This allows programs to handle data of unknown size or size that can vary during runtime. In C++, dynamic memory is managed using the heap, which is a special area of memory used for dynamic allocations.
new
resides in the heap, and it persists until it is explicitly deallocated using delete
.new
OperatorThe new
operator is used to allocate memory for a single variable or an array of variables. The syntax is as follows:
data_type* pointer = new data_type;
pointer
: A pointer to the allocated memory.data_type
: The type of the variable to be allocated.new
operator returns a pointer to the allocated memory.
data_type* array_pointer = new data_type[array_size];
array_size
: The number of elements in the array to be allocated.new
operator returns a pointer to the first element of the array.
#include <iostream>
using namespace std;
int main() {
// Dynamically allocate memory for an integer
int* p = new int;
// Assign a value to the dynamically allocated memory
*p = 10;
cout << "Value of p: " << *p << endl;
// Free the dynamically allocated memory
delete p;
return 0;
}
Output:
Value of p: 10
Explanation:
new int
allocates memory for a single integer on the heap.p
holds the memory address where the integer is stored.*p
to assign and access the value.delete
operator frees the memory after it is no longer needed.delete
OperatorThe delete
operator is used to deallocate memory that was previously allocated using the new
operator. It releases the memory back to the heap, ensuring that there is no memory leak.
delete pointer;
pointer
: A pointer to the dynamically allocated memory.
delete[] array_pointer;
array_pointer
: A pointer to the first element of the dynamically allocated array.delete[]
to correctly delete arrays, as it ensures each element is deallocated properly.
#include <iostream>
using namespace std;
int main() {
// Dynamically allocate memory for an array of 5 integers
int* arr = new int[5];
// Assign values to the array
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
}
// Print the values
cout << "Array values: ";
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
cout << endl;
// Free the dynamically allocated memory
delete[] arr;
return 0;
}
Output:
Array values: 0 10 20 30 40
Explanation:
new int[5]
allocates an array of 5 integers on the heap.delete[] arr
to free the memory.Memory leaks occur when dynamically allocated memory is not deallocated, causing the program to consume memory indefinitely. This can lead to performance degradation or even crashes, especially in long-running applications.
delete
or delete[]
when you no longer need it.new
and delete
for automatic variables (local variables). Instead, rely on automatic storage duration and stack allocation when possible.std::unique_ptr
, std::shared_ptr
) from the C++ Standard Library for automatic memory management in modern C++.nullptr
after deleting them to avoid dangling pointers.In modern C++, it’s recommended to use smart pointers provided in the <memory>
header to manage dynamic memory automatically. Smart pointers ensure that memory is automatically deallocated when it is no longer needed, reducing the risk of memory leaks.
std::unique_ptr
#include <iostream>
#include <memory>
using namespace std;
int main() {
// Create a unique pointer that automatically deletes the allocated memory
unique_ptr<int> ptr = make_unique<int>(10);
cout << "Value: " << *ptr << endl;
// No need to call delete explicitly; unique_ptr handles it
return 0;
}
In this example:
unique_ptr
automatically deletes the dynamically allocated memory when it goes out of scope, making manual memory management unnecessary.