There are situations when the input data is assigned during program execution. For instance, the roster of employees grows as new staff members join the company and shrinks when someone exits. This process is known as memory management. Now, let's delve into the topic of dynamic memory allocation.
Memory allocation
Reserving or assigning memory to a variable is referred to as memory allocation. There are two methods to allocate memory for storing data:
- Static allocation or compile-time allocation - This method involves allocating space for the variable where the size and data type are predetermined and remain fixed during the program execution.
- Dynamic allocation or run-time allocation - This approach involves allocating memory dynamically, where the size of the variable is not predetermined. Dynamic memory allocation heavily relies on the use of pointers.
Why Dynamic memory allocation?
Dynamically, storage allocation can occur during program execution, but it's not possible to generate variables spontaneously. Therefore, two conditions must be met for dynamic memory allocation:
- A dynamic memory space is required.
- The storage address for variable access must be stored in memory.
Likewise, we perform memory deallocation for the variables stored in memory.
In C++, the memory is partitioned into two primary sections:
-
- Stack: Memory allocated for variables declared within functions is sourced from the stack.
-
- Heap: This segment represents unallocated memory in the application typically employed for dynamic memory allocation purposes.
Dynamic memory allocation using the new operator
To dynamically assign memory space, the new operator is employed. This involves generating a memory allocation request within the free store. Upon availability of memory, initialization occurs, and the pointer variable receives the address of the allocated space.
Syntax
Pointervariable = new datatype;
The pointer_varible represents a memory address pointing to a specific data type, such as int, float, string, char, and more.
Example
int *m = NULL // Initially we have a NULL pointer
Memory is allocated to the variable when 'new int' is used to create an integer instance.
It can be explicitly defined by including the subsequent statement on a single line -
int *m = new int
Initialize memory
We can also initialize memory using new operator.
For example
int *m = new int(20);
Float *d = new float(21.01);
Allocate a block of memory
We can employ a different operator to reserve a block (array) of a specific data type.
For example
int *arr = new int[10]
Here we've dynamically reserved memory for a collection of ten integers, providing a pointer to the initial array element. Consequently, arr[0] represents the first element, proceeding in sequence.
- Contrasting a standard array creation with memory allocation through new, normal arrays are automatically deallocated by the compiler. However, dynamically created blocks persist until explicitly deleted by the programmer or program termination.
- In cases where heap memory lacks sufficient space, a new memory allocation request fails, triggering an exception (std::bad_alloc) unless nonthrow is specified with the new operator. Therefore, it is advisable to validate the pointer variable beforehand as a best coding practice.
int *m = new(nonthrow) int;
if(!m) // check if memory is available
{
cout<< "No memory allocated";
}
Now that we have dynamically assigned memory, it's important to understand the process of deallocating it.
Delete operator
We deallocate memory in C++ by utilizing the delete operator.
Syntax
delete pointervariablename
Example
delete m; // free m that is a variable
delete arr; // Release a block of memory
Example to demonstrate dynamic memory allocation
// The program will show the use of new and delete
#include <iostream>
using namespace std;
int main ()
{
// Pointer initialization to null
int* m = NULL;
// Request memory for the variable
// using new operator
m = new(nothrow) int;
if (!m)
cout<< "allocation of memory failed\n";
else
{
// Store value at allocated address
*m=29;
cout<< "Value of m: " << *m <<endl;
}
// Request block of memory
// using new operator
float *f = new float(75.25);
cout<< "Value of f: " << *f <<endl;
// Request block of memory of size
int size = 5;
int *arr = new(nothrow) int[size];
if (!arr)
cout<< "allocation of memory failed\n";
else
{
for (int i = 0; i< size; i++)
arr[i] = i+1;
cout<< "Value store in block of memory: ";
for (int i = 0; i< size; i++)
cout<<arr[i] << " ";
}
// freed the allocated memory
delete m;
delete f;
// freed the block of allocated memory
delete[] arr;
return 0;
}
Output
Value of m: 29
Value of f: 75.25
Value store in block of memory: 1 2 3 4 5