C++ Dynamic Memory

Understanding how dynamic memory works in C++ is essential to becoming a qualified C++ programmer. Memory in a C++ program is divided into two parts:

  • Stack:All variables declared inside a function will occupy stack memory.
  • Heap:This is memory not used by the program, which can be used for dynamic memory allocation during program execution.

Often, you cannot predict in advance how much memory is needed to store specific information in a defined variable; the required memory size can only be determined at runtime.

In C++, you can use special operators to allocate memory in the heap for variables of a given type at runtime, which returns the address of the allocated space. These operators are thenewOperators.

If you no longer need dynamically allocated memory space, you can usedeleteoperator to delete the memory previously allocated by the new operator.

new and delete operators

The following is the general syntax for using the new operator to dynamically allocate memory for any data type:

new data-type;

Here,data-typeIt can be any built-in data type, including arrays, or any user-defined data type, including classes or structures. Let's first look at built-in data types. For example, we can define a pointer to a double type, then request memory, which is allocated at execution time. We can use the following statement:newoperators to accomplish this:

double* pvalue = NULL; // pointer initialized to null pvalue = new double; // request memory for the variable

If the free store has been exhausted, memory allocation may not succeed. Therefore, it is recommended to check whether the new operator returns a NULL pointer and take appropriate action as follows:

double* pvalue = NULL; if( !(pvalue = new double )) { cout << "Error: out of memory." <<endl; exit(1); }

malloc()The malloc() function appeared in C language and still exists in C++, but it is recommended to avoid using malloc() whenever possible. Compared with malloc(), the main advantage of new is that new not only allocates memory, but also creates objects.

At any time, when you feel that a variable with dynamically allocated memory is no longer needed, you can use the delete operator to free the memory it occupies, as shown below:

delete pvalue;        // 释放 pvalue 所指向的内存

The following example uses the above concept and demonstrates how to use the new and delete operators:

Example

#include <iostream> using namespace std; int main () { double* pvalue = NULL; // pointer initialized to null pvalue = new double; // request memory for the variable *pvalue = 29494.99; // store value at the allocated address cout << "Value of pvalue : " << *pvalue << endl; delete pvalue; // release memory return 0; }

When the above code is compiled and executed, it produces the following results:

Value of pvalue : 29495

Dynamic memory allocation for arrays

Suppose we want to allocate memory for a character array (a string with 20 characters). We can use the syntax from the above example to dynamically allocate memory for the array, as shown below:

char* pvalue  = NULL;   // 初始化为 null 的指针
pvalue  = new char[20]; // 为变量请求内存

To delete the array we just created, the statement is as follows:

delete [] pvalue;        // 删除 pvalue 所指向的数组

The following is the general syntax of the new operator that can allocate memory for multi-dimensional arrays, as shown below:

One-dimensional array

// dynamic allocation, array length is m int *array=new int [m]; //release memory delete [] array;

Two-dimensional array

int **array; // assume the first dimension of the array has length m, and the second dimension has length n // dynamically allocate space array = new int *[m]; for( int i=0; i<m; i++ ) { array[i] = new int [n]; } //release for( int i=0; i<m; i++ ) { delete [] array[i]; } delete [] array;

2D array instance test:

Example

#include <iostream> using namespace std; int main() { int **p; int i,j; //p[4][8] //start allocating two-dimensional data with 4 rows and 8 columns p = new int *[4]; for(i=0;i<4;i++){ p[i]=new int [8]; } for(i=0; i<4; i++){ for(j=0; j<8; j++){ p[i][j] = j*i; } } //print data for(i=0; i<4; i++){ for(j=0; j<8; j++) { if(j==0) cout<<endl; cout<<p[i][j]<<"\t"; } } //start releasing the allocated heap for(i=0; i<4; i++){ delete [] p[i]; } delete [] p; return 0; }

Three-dimensional array

int ***array; // assume the array's first dimension is m, the second is n, and the third is h // dynamically allocate space array = new int **[m]; for( int i=0; i<m; i++ ) { array[i] = new int *[n]; for( int j=0; j<n; j++ ) { array[i][j] = new int [h]; } } //release for( int i=0; i<m; i++ ) { for( int j=0; j<n; j++ ) { delete[] array[i][j]; } delete[] array[i]; } delete[] array;

3D array test instance:

Example

#include <iostream> using namespace std; int main() { int i,j,k; // p[2][3][4] int ***p; p = new int **[2]; for(i=0; i<2; i++) { p[i]=new int *[3]; for(j=0; j<3; j++) p[i][j]=new int[4]; } //output three-dimensional data p[i][j][k] for(i=0; i<2; i++) { for(j=0; j<3; j++) { for(k=0;k<4;k++) { p[i][j][k]=i+j+k; cout<<p[i][j][k]<<" "; } cout<<endl; } cout<<endl; } // release memory for(i=0; i<2; i++) { for(j=0; j<3; j++) { delete [] p[i][j]; } } for(i=0; i<2; i++) { delete [] p[i]; } delete [] p; return 0; }

Dynamic memory allocation for objects

Objects are no different from simple data types. For example, look at the following code; we will use an array of objects to clarify this concept:

Example

#include <iostream> using namespace std; class Box { public: Box() { cout << "Calling constructor!" <<endl; } ~Box() { cout << "Calling destructor!" <<endl; } }; int main( ) { Box* myBoxArray = new Box[4]; delete [] myBoxArray; // delete array return 0; }

If you want to allocate memory for an array containing four Box objects, the constructor will be called 4 times; similarly, when these objects are deleted, the destructor will also be called the same number of times (4 times).

When the above code is compiled and executed, it produces the following results:

Calling constructor!
Calling constructor!
Calling constructor!
Calling constructor!
Calling destructor!
Calling destructor!
Calling destructor!
Calling destructor!
other extensions