provide necessary support for
C++'s powerful dynamic memory allocation system.
Dynamic Allocation is the means by which a program can obtain memory during runtime.
The
global and local variables are allocated memory during compile-time. However, you cannot add any global or local
variables during runtime. What if, your program needs to use a variable amount of memory ? In such a case, you would need to allocate memory during runtime, as and when needed. And of course, here the dynamic allocation routines can serve the purpose.
C++ Dynamic Memory Allocation Operator
C++ dynamic allocation routines obtain memory for allocation from the
free store, the pool of unallocated heap memory provided to the program. C++ defines two unary
operator new and delete that perform the task of allocating and freeing (deallocating) memory during runtime. Since these operator new and delete operate upon free store memory, they are also called free store operator.
The operator new can be used to create
objects of all types, including a
class name.
The general form of object creation using new is as follows :
pointer-variable = new data-type ;
where data-type is any valid
C++ data type and the pointer-type is a pointer of type data-type. The operator new will allocate memory of size equal of size of specified data-type and return a pointer (of the specified data-type) pointing to the newly allocated area. For example, the following code fragment
Storing Initial Values will allocate sufficient amount of memory from free store to hold a value of specified data-type and store the starting address of the newly allocated memory of iptr. Since new is allocating the memory for int type, the receiving pointer must also be of type int i.e., iptr must be of int type for the above given assignment. Similarly, for the following assignments
cptr = new char ;
fptr = new float ;
cptr is a pointer of type char and fptr is a pointer of type float. The pointers cptr and fptr must be already declared as pointers of appropriate types before the above assignments. Alternatively, the declaration and assignment of pointers can be combined as follows :
char ∗cptr = new char ;
float ∗fptr = new float ;
Once a pointer points to newly allocated memory, data values can be stored there using the "at address" operator ∗ of pointers, as it is shown below :
∗cptr = 'a' ;
∗fptr = 17.32 ;
The above assignment will assign 'a' to the newly created char object and 17.32 to the float object. The newly allocated memory (through new) can be initialized at the time of allocation itself. This is done as follows :
pointer-variable = new data-type (value) ;
where value is the initial value to be stored in the newly allocated memory. The value must also be of the specified data-type type.
Consider the following statements :
char ∗cptr = new char ('a') ; //statement 1
float ∗fptr = new float (17.32) ; //statement 2
The above given statement 1 will allocate sufficient memory from free pool to hold a character, store 'a' inside this newly allocated memory, and make character pointer cptr point to this area. Similarly, the statement2 will allocate sufficient memory from free pool to hold a floating-point value, store 17.32 inside this newly allocated memory, and make float pointer fptr point to this area.
Creating Dynamic Array in C++
The new operator can also allocator memory for user-defined types like structures, arrays, and classes. To allocate memory for a one-dimensional arrays, new may be used in the following form :
pointer-variable = new data-type[size] ;
where size is the size of the 1-D array i.e., number of elements in the array. To allocate memory space for an int array value[10], we will give
int ∗ value = new int[10] ;
It will create memory space from the free store for an array of 10 integers. Now forth value[0] will refer to the first element of the array, value[1] will refer to the second element, and so on. No initializers could be specified for arrays until C++11 arrived.
But C++11 standard allows you to initialize dynamic arrays with an initialize list e.g.,
int ∗value = new int[5] {11, 12, 13, 14, 15} ;
Note - The lifetime of an object created by new is not restricted to the scope in which it is created. It lives in the memory until explicitly deleted using the delete operator.
When an object, created through new, is no longer needed, it must be destroyed so that the memory space occupied by it may be released for reuse. This can be done with the help of delete operator, the memory deallocation operator of C++. The general form of delete is as shown below :
delete pointer-variable ;
where pointer-variable is the pointer that points to a data object created with new. For example,
The arrays allocated through new are freed using the following form of delete :
delete[size] pointer-variable ;
where size is the number of elements in the array being pointed to by pointer-variable.
But, in recent versions of C++, size is not required i.e., as shown below :
delete[] array-pointer-variable ;
C++ Dynamic Memory Allocation Example
Here is an example demonstrating the dynamic memory allocation in C++, or demonstrates the working of the new and the delete operator in C++
/* C++ Dynamic Memory Allocation Example Program */
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int *rollno; // declares an integer pointer
float *marks; // declares a float pointer
void main()
{
clrscr();
int size, i;
cout<<"How many elements for the array ? ";
cin>>size;
rollno = new int[size]; // dynamically allocate rollno array
marks = new float[size]; // dynamically allocate marks array
// first check, whether the memory is available or not
if((!rollno) || (!marks)) // if rollno or marks is null pointer
{
cout<<"Out of Memory..!!..Aborting..!!\n";
cout<<"Press any key to exit..";
getch();
exit(1);
}
// read values in the array elements
for(i=0; i<size; i++)
{
cout<<"Enter rollno and marks for student "<<(i+1)<<"\n";
cin>>rollno[i]>>marks[i];
}
// now display the array contents
cout<<"\nRollNo\t\tMarks\n";
for(i=0; i<size; i++)
{
cout<<rollno[i]<<"\t\t"<<marks[i]<<"\n";
}
delete[]rollno; // deallocating rollno array
delete[]marks; // deallocating marks array
getch();
}
Here is the sample run of the above C++ program, demonstrating the operator new and delete in C++
As you can see, the above C++ program first ask from the user to enter the size of the array and then allocates space for them dynamically. If the sufficient space is not available, it exits after displaying an error message. And if the sufficient space is available, then it reads the data into the arrays and finally displays them. And before exiting the program, it deallocates the occupied space using the delete operator, so that it becomes available for reuse.
Here is another C++ example program demonstrates the same concept, i.e., the working of new and the delete operator of C++, or demonstrates the dynamic memory allocation in C++. But in this version of C++ program, the array used is two-dimensional array. This C++ program reads a 2-D array and then prints them back on the screen, along with row-sums and column-sums.
/* C++ Dynamic Memory Allocation Example Program
* This is the same program as above, but this
* program uses two-dimensional array to demonstrates
* dynamic memory allocation in C++. This C++ program
* also displays the rowsum and the colsum of the array */
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
clrscr();
int *val, *rows, *cols;
int maxr, maxc, i, j;
cout<<"Enter the dimension of the array (row col): ";
cin>>maxr>>maxc;
val = new int[maxr * maxc];
rows = new int[maxr];
cols = new int[maxc];
for(i=0; i<maxr; i++)
{
cout<<"\nEnter elements for row "<<i+1<<" : ";
rows[i] = 0;
for(j=0; j<maxc; j++)
{
cin>>val[i*maxc + j];
rows[i] = rows[i] + val[i*maxc + j];
}
}
for(j=0; j<maxc; j++)
{
cols[j] = 0;
for(i=0; i<maxr; i++)
{
cols[j] = cols[j] + val[i*maxc + j];
}
}
cout<<"\nThe given array in two dimensional (alongwith rowsum and colsum) is :\n";
for(i=0; i<maxr; i++)
{
for(j=0; j<maxc; j++)
{
cout<<val[i*maxc + j]<<"\t";
}
cout<<rows[i]<<"\n";
}
for(j=0; j<maxc; j++)
{
cout<<cols[j]<<"\t";
}
cout<<"\n";
getch();
}
Here is the sample run of the above C++ program. This is the array along with rowsum and colsum:
Memory Leaks in C++
Improper use of new and delete may lead to memory leaks. Make sure the memory allocated through new must be properly deleted through delete.
There is no doubt about the fact that new and delete are very useful. But they have an associated problem that it is easy to forget to delete something that was previously allocated with new, leaving an orphaned memory black - a block that is still allocated but which has nothing referencing it.
A certain function that dynamically allocates memory to some object but forgets to deallocate the reserved memory, consumes some amount of memory every time it is executed. Thus, a part of memory disappears with its every run, and eventually the amount of memory consumed has an adverse effect on the system. This situation is known as a memory leak.
Many possible reason lead to the situation of memory leaks. Most common of these are :
- forgetting to delete something that has been dynamically allocated (i.e., using new)
- falling to notice that code may bypass a delete statement under certain circumstances
- assigning the result of a new statement to a pointer that was already pointing to an allocated object.
These reasons that cause memory leaks must be carefully dealt with while writing a program.