C++ dynamic memory


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

  • Stack: All variables declared inside the function will occupy stack memory.

  • Heap: This is unused memory in the program and can be used to dynamically allocate memory while the program is running.

Many times, you cannot predict in advance how much memory is needed to store specific information in a defined variable. The amount of memory required needs to be determined at runtime.

In C++, you can allocate memory on the heap at runtime for a variable of a given type using special operators, which return the address of the allocated space. This operator is the new operator.

If you do not need to dynamically allocate memory, you can use the delete operator 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 -type can be any built-in data type including arrays, or any user-defined data type including classes or structures. Let's look at the built-in data types first. For example, we could define a pointer to type double and then request memory, which is allocated at execution time. We can accomplish this using the new operator as follows:

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

If the free storage area has been used up, memory allocation may not be successful. Therefore, it is recommended to check whether the new operator returns a NULL pointer and take the following appropriate actions:

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

}

malloc() The function appeared in the C language and still exists in C++, but It is recommended not to use the malloc() function as much as possible. The main advantage of new compared to the malloc() function is that new not only allocates memory, it also creates objects.

At any time, when you feel that a variable that has been dynamically allocated memory is no longer needed, you can use the delete operator to release the memory it occupies, as follows:

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

The above concepts are used in the following example, demonstrating how to use the new and delete operators:

#include <iostream>
using namespace std;

int main ()
{
   double* pvalue  = NULL; // 初始化为 null 的指针
   pvalue  = new double;   // 为变量请求内存
 
   *pvalue = 29494.99;     // 在分配的地址存储值
   cout << "Value of pvalue : " << *pvalue << endl;

   delete pvalue;         // 释放内存

   return 0;
}

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

Value of pvalue : 29495

Dynamic memory allocation of arrays

Suppose we want to allocate memory for a character array (a string of 20 characters), we can use the syntax in the above example to dynamically allocate memory for the array, as follows Display:

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, which can allocate memory for multi-dimensional arrays, as follows:

int ROW = 2;
int COL = 3;
double **pvalue  = new double* [ROW]; // 为行分配内存

// 为列分配内存
for(int i = 0; i < COL; i++) {
    pvalue[i] = new double[COL];
}

Release multidimensional array memory:

for(int i = 0; i < COL; i++) {
    delete[] pvalue[i];
}
delete [] pvalue;

Dynamic memory allocation of objects

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

#include <iostream>
using namespace std;

class Box
{
   public:
      Box() { 
         cout << "调用构造函数!" <<endl; 
      }
      ~Box() { 
         cout << "调用析构函数!" <<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 the 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:

调用构造函数!
调用构造函数!
调用构造函数!
调用构造函数!
调用析构函数!
调用析构函数!
调用析构函数!
调用析构函数!