SEARCH THIS BLOG

DYNAMIC ALLOCATION OPERATORS

Computer's memory is an interesting thing. The way it works is so complex yet highly interesting.

Dynamic Allocation Operators

Pointers provide necessary support for C++’s powerful dynamic memory allocation system. As you know, dynamic allocation is the means by which a program can obtain memory during runtime. The global and the 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 variable amount of memory space? In such case, you would need to allocate memory during runtime, as and when required. This can be done using the dynamic allocation operators.


DYNAMIC ALLOCATION OPERATORS IN C++

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 operators new and delete that perform the task of allocating and freeing (deallocating) memory during runtime. In addition to these two operators, the C language functions malloc() and calloc() are also defined in C++. Since all these operate on the free memory, they are collectively called free store operators & functions. We will focus on new and delete. However, here’s a brief about malloc() and calloc() :

 

malloc() 


It is a C based dynamic memory allocator used to allocate memory from heap region during runtime. It is included in the header cstdlib.

The general syntax for malloc() is :

 

pointer_name = (* data_type) malloc (size) ;

 

pointer_name  is a pointer to type data_type.

data_type is the type of values you want to store in the memory.

size is the total number of memory blocks of type data_type you want.

 

malloc() is generally used to create dynamic arrays. It searches the memory for a suitable address where the array of proper size can be created and returns the base address of the first memory block. If it fails to allocate memory, it returns NULL. It is important to note that malloc() only allocates memory but does not initialize it. Therefore, all the allocated memory contains garbage value.

 

calloc() 


It is also an inbuilt function included in the header file cstdlib. It is used to allocate memory from heap region during runtime.

The general syntax is :

pointer_name = (*data_type) calloc (no_of_blocks , size_of_each_block) ;

 

pointer_name is a pointer of type data_type

data_type is the type of values to be stored in the memory

no_of_blocks is an integer denoting the number of continuous memory blocks required

size_of_each_block denotes size of each memory block in bytes.

 

If calloc() fails to allocate memory, it returns a NULL. Also, unlike malloc(), it allocates and also initializes the memory blocks with legal default value depending on the data_type.

Learn all about malloc() and calloc() here. (link will be ready shortly.)

 

The ‘new’ operator 

The operator new can be used to create objects of all kinds, including user defined data types such as class or structures.


The general syntax for object creation using new :


pointer_name = new data_type ;


where data_type is any valid C++ data type and the pointer_name is a pointer variable of type data_type.


The operator new will allocate memory of size equal  to the size of given data_type and return a pointer (of that specified data_type) pointing to the base address of the newly allocated area.


For instance, the following code snippet

iptr = new int ;


This will allocate sufficient amount of memory from free storage to hold a value of specified data_type and store the starting address of the newly allocated memory in iptr. Since new is allocating the memory for int type, the receiving pointer must be of int type i.e. iptr must be an int pointer.


Declaration and allocation can be combined in one statement as :


int * iptr = new int ;

 

Once a pointer points to a legal memory, we can access that memory using the “value at” operator * of pointers as shown below :

*iptr = 12 ;


The above assignment will assign the integer value 12 into the newly allocated memory block.


This assignment can also be done at the time of allocation as :

pointer_name = 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.33);   // statement 2

 

The above given statement 1 will allocate sufficient memory from free pool to hold a character, then store ‘a’ inside this newly allocated memory, and make character pointer cptr point to this memory address.

Similarly, the statement 2 will allocate sufficient memory from free pool to hold a floating point value, then store 17.33 inside that newly allocated memory, and make float pointer fptr point to that memory address.

 

Creating Dynamic Array 

The operator new can also allocate memory for user defined types like structures and classes as well as for derived data types like arrays. To allocate memory for a one-dimensional array, new may be used in the following form :

pointer_name = new data_type [size] ;


where size is an integer representing the number of elements in the array.

For instance, to allocate memory for an array having 10 integer elements we need to use new as :

int * a = new int [10] ;

This will create an array of size 10 with a pointing to the base address of the first element. Now all these array elements can be accessed as

a[0] for the first element

a[1] for the second element

a[2] for the third element….and so on.

 

Before C++11 standards, no initializations were possible at the time of creation of array but now we can also initialize the array with some initial values as 

int * a = new int [5] {2, 5, 3, 8, 10} ;

This creates an array a with a[0] = 2, a[1] = 5 and so on.

 

The new operator does not initialize the newly created memory unless explicitly forced by the programmer.

See the following code and its output :

#include<iostream>

using namespace std;

int main()

{

int * a= new int;

cout<< *a;

return 0;

}

 

Output :

1448160 


The output is certainly a garbage value which is at present stored in the newly created memory.

 

Now see this code :

 #include<iostream>

using namespace std;

int main()

{

int * a= new int ();      // explicitly forcing initialization

cout<< *a;

return 0;

}

 

Output :

0


As evident from above examples, to initialize memory allocated through new, the program needs to force this initialization explicitly. Also, arrays can be initialized with legal default values in the same way.

int * a= new int [5]();

This code creates an array of 5 elements and initializes the elements with the default value of int type, i.e. 0.

 

In older versions of C++, it was not possible to create a static array of variable size. For example,

int n;

cin>>n;

int a[n];

The above code would generate error as a variable has been passed as the size of array. But the new standards allow such creations and so the use of dynamic creation of arrays has now reduced.

 

An important note :

Since the program’s free store (heap) is not infinite, during the course of program execution, it may become exhausted i.e. the program may run out of heap memory and more memory may not be allocated further. To be on the safer side in such a situation, whenever you allocate memory, you must check the value returned by new operator to make sure it is not NULL or zero before using the pointer. Using a NULL pointer will almost certainly crash the system.

int *val = new int;

if(val)

   *val=7;

else

    cout<<”Out of memory !!” ;

 

Even if, the initial value is given in the expression, initialization is done only if the value returned by operator new is nonzero (or non-NULL). If the value returned by new is 0 (NULL), the value of entire expression becomes 0 (i.e. false).

 

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_name ;

where pointer_name is the pointer that points to a data object created through new.

For deleting dynamic arrays created by new, we use the following syntax :

delete [] pointer_name ;

 

Note : When we apply delete to a pointer, it essentially deletes that memory which the pointer is pointing to. It does not mean that the pointer itself is deleted. Any pointer is first a static variable itself and it remains in memory for its entire scope. 

 

 

 

 

 

If you like this article share with your friends.

Do not stop here. Read all articles related to C++ here.

If you have any doubts, queries or suggestions for the website, please comment on this post.

If you want to contribute any article for the website, feel free to share it on coding.nkcoder@gmail.com. We will publish it on the website with your name.

Download the pdf form of this article here.

Related Topics :

Introduction to Pointers

Static & Dynamic Memory Allocations

Declaration and Initialization of pointers

Pointer Arithmetic

Memory Leaks

Pointers & Constants

 


Post a Comment