C + + dynamic memory allocation

Posted by fredted40x on Sat, 18 Sep 2021 00:01:24 +0200

Transferred from: https://www.cnblogs.com/yingying0907/archive/2012/07/31/2616975.html

1. Heap memory allocation:

C/C + + defines four memory intervals:
Code area, global variable and static variable area, local variable area, i.e. stack area, and dynamic storage area, i.e. heap area or free store area.
Concept of heap:
A variable (or object) is usually defined. The compiler can know the size of the required memory space according to the type of the variable (or object) during compilation, so that the system can allocate a determined storage space for them at an appropriate time. This memory allocation is called static storage allocation;
Some operation objects can only be determined when the program is running, so the storage space cannot be reserved for them during compilation. Only when the program is running, the system allocates memory according to the requirements of the runtime. This method is called dynamic storage allocation. All dynamic storage allocations are made in the heap.
When the program needs a dynamically allocated variable or object, it must apply to the system to obtain a storage space of the required size in the heap for storing the variable or object. When the variable or object is no longer used, that is, at the end of its life, the storage space occupied by it should be explicitly released, so that the system can reallocate the heap space and reuse the limited resources.

2. Allocation and release of heap memory

Methods of heap space application and release:
In C + +, the application and release of the allocated storage space in the heap are completed by using new and delete operators respectively:

Pointer variable name = new type name (initializer);
delete pointer name;
For example: 1. int *pi=new int(0);
It is roughly equivalent to the following code sequence:
2,int ival=0, *pi=&ival;
Difference: the variable pointed to by pi is allocated by the library operator new(), located in the heap of the program, and the object is unnamed.   
Heap space application and release instructions:
(1). new operator returns a pointer to the allocated type variable (object). The created variables or objects are operated indirectly through the pointer, and the dynamically created object itself has no name.
⑵. Generally, when defining variables and objects, they should be named with identifiers, named objects, and dynamic nameless objects (please note that they are completely different from the temporary objects in the stack: different life cycles, different operation methods, and temporary variables are transparent to programmers).
(3) heap area will not be automatically initialized (including Zeroing) during allocation, so it must be explicitly initialized with initializer. The operation sequence of the new expression is as follows: allocate an object from the heap, and then initialize the object with the value in parentheses.

3. Reactor space application and release demonstration:

(1) explicitly initialize with initializer

int *pi=new int(0);

(2) when the pi life cycle ends, the target pointed to by the pi must be released:

  delete pi;

Note that the memory space of the target referred to by pi is released, that is, the target is revoked, which is called dynamic memory deallocation. However, the pointer PI itself is not revoked, it still exists, and the memory space occupied by the pointer is not released.
The following is a description of the new operation
(1). new operator returns a pointer to the allocated type variable (object). The created variables or objects are operated indirectly through the pointer, while the dynamically created object itself has no name.
⑵. Generally, when defining variables and objects, they should be named with identifiers, named objects, and dynamic nameless objects (please note that they are completely different from the temporary objects in the stack: different life cycles, different operation methods, and temporary variables are transparent to programmers).
(3) heap area will not be automatically initialized (including Zeroing) during allocation, so it must be explicitly initialized with initializer. The operation sequence of the new expression is as follows: allocate an object from the heap, and then initialize the object with the value in parentheses.

4. Create a dynamic one-dimensional array in the heap

① Request array space:
Pointer variable name = new type name [subscript expression];
Note: "subscript expression" is not a constant expression, that is, its value does not have to be determined at compile time, but can be determined at run time.
② Free array space:
delete [] pointer variable name pointing to the array;
Note: square brackets are very important. If square brackets are missing in the delete statement, because the compiler thinks that the pointer points to the first element of the array, there will be a problem of incomplete recycling (only the space occupied by the first element is recycled). After square brackets are added, it will be converted into a pointer to the array and the whole array will be recycled. The number of array elements does not need to be filled in the square brackets of delete [], which is known by the system. Even if it is written, the compiler ignores it.

#include <iostream.h>
#include <string.h>
void main(){
     int n;
     char *pc;
     cout<<"Please enter the number of elements of the dynamic array"<<endl;
     cin>>n; //n to determine at run time, enter 17
     pc=new char[n]; //Apply for memory space of 17 characters (8 Chinese characters and one terminator can be installed)
     strcpy(pc,""Dynamic allocation of heap memory");//
     cout<<pc<<endl;
     delete []pc;//Release the memory space of n characters pointed by pc
     return ; }

5. Description of dynamic one-dimensional array

① Variable n has no definite value at compile time, but is input at run time, and heap space is allocated according to the needs of run time. This is the advantage of dynamic allocation, which can overcome the disadvantage of "large opening and small use" of array. The algorithm in table, sorting and lookup has better universality if dynamic array is used. It must be noted that delete []pc frees up the space of n characters, while delete pc frees up only one character space;
② If there is a char *pc1 and pc1=p, delete [] pc1 can also be used to free up the space. Although C + + does not check the boundaries of arrays, the size of space allocated to arrays is recorded during heap space allocation.
③ Array cannot be initialized without initializer.

6. Pointer array and array pointer

Pointer type:
(1)intptr;// The type pointed to by the pointer is int
(2)charptr;// The type pointed to by the pointer is char
(3)int**ptr;// The type pointed to by the pointer is int * (that is, an int * pointer)
(4)int(*ptr)[3];// The type pointed to by the pointer is int()[3] / / declaration of two-dimensional pointer

  • Pointer array:
    An array stores pointers of the same type, which is usually called a pointer array.
    For example, int * a[2]; It contains two int * variables
int * a[2];
a[0]= new int[3];
a[1]=new int[3];
delete a[0];
delete a[1];

Note that this is an array and cannot delete [];

  • Array pointer:
    A pointer to a one - dimensional or multi - dimensional array
    int * b=new int[10]; Pointer to one-dimensional array B;
    Note that delete [] must be used to free space at this time, otherwise memory leakage will occur, and b will become a null pointer
    int (*b2)[10]=new int[10][10]; Note that B2 here points to the first address of a two - dimensional int array
    Note: here, b2 is equivalent to the two-dimensional array name, but its boundary is not indicated, that is, the number of elements in the highest dimension, but the number of elements in the lowest dimension must be specified! Just like a pointer to a character, that is, it is equivalent to a string. Don't say that a pointer to a character is a pointer to a string.
int(*b3) [30] [20];  //Three level pointer ― > pointer to three-dimensional array;
int (*b2) [20];     //Secondary pointer; -- > Pointer to a two-dimensional array;
b3=new int [1] [20] [30];
b2=new int [30] [20];
//The following formula can be used to delete these two dynamic arrays:
delete [] b3;  //Delete (release) 3D array;
delete [] b2;  //Delete (release) two-dimensional array;
//Create a dynamic multidimensional array in the heap
//new type name [subscript expression 1] [subscript expression 2];
//For example: create a dynamic 3D array
float (*cp)[30][20] ;  //Points to an array of 30 rows and 20 columns
                             //Pointer to a two-dimensional array
cp=new float [15] [30] [20];
      //Establish an array composed of 15 30 * 20 arrays;

Note: cp is equivalent to a three-dimensional array name, but it does not indicate its boundary, that is, the number of elements in the highest dimension. Just like a pointer to a character, it is equivalent to a string. Do not say that a pointer to a character is a pointer to a string. This is consistent with the nested definition of arrays.

float(*cp) [30] [20];  //Three level pointer;
      float (*bp) [20];     //Secondary pointer;
      cp=new float [1] [20] [30];
      bp=new float [30] [20];
     //Both arrays are composed of 600 floating-point numbers. The former is a three-dimensional array with only one element, each element is a two-dimensional array with 30 rows and 20 columns, while the other is a two-dimensional array with 30 elements, each element is a one-dimensional array with 20 elements.
      // The following formula can be used to delete these two dynamic arrays:
delete [] cp;  //Delete (release) 3D array;
//1. Let's first look at the dynamic creation of two-dimensional arrays:
void main(){
    double **data;
    data = new double*[m]; //Application line
    if ((data ) == 0)
     { cout << "Could not allocate. bye ...";
        exit(-1);}
    for(int j=0;j<m;j++)
     { data[j] = new double[n]; //Set column
        if (data[j] == 0)
        { cout << "Could not allocate. Bye ...";
           exit(-1);}  } //After the space application is completed, the next step is initialization
    for (int i=0;i<m;i++)
       for (int j=0;j<n;j++)  data[i][j]=i*n+j;
display(data); //2. Output of two-dimensional array, omitted here.
//3. Let's look at the undo and memory release of two-dimensional arrays:
   for (int i=0;i<m;i++)
         delete[] data[i];
      //Note the undo order, column first and row later, which is opposite to the setting
    delete[] data;
    return;
}

The memory release of two-dimensional arrays can be made into functions,
Call statement de_allocate(data);

void de_allocate(double **data){
       for (int i=0;i<m;i++)    delete[] data[i];
       delete[] data;
       return; }

Making heap space through pointer, several possible problems in programming
(1) dynamic allocation failed. A NULL pointer (NULL) is returned, indicating that an exception occurred, insufficient heap resources and allocation failure.

  data = new double*[m]; //Application line
  if ((data ) == 0)......

(2) pointer deletion and heap space release. Deleting a pointer P (delete p;) actually means deleting the target (variable or object, etc.) referred to by P and freeing its heap space instead of deleting P itself. After freeing the heap space, P becomes an empty pointer and can no longer use the space through P. before re assigning a value to P, P can no longer be used directly.
(3) memory leak and repeated release. New and delete are used in pairs. Delete can only free heap space. If the pointer value returned by new is lost, the allocated heap space cannot be recovered, which is called memory leakage. Repeated release of the same space is also dangerous, because the space may have been allocated, so the pointer returned by new must be properly saved to ensure that there is no memory leakage and that the heap memory space will not be released again.
(4) lifetime of dynamically allocated variables or objects. The lifetime of an anonymous object does not depend on its scope. For example, a dynamic object established in a function can still be used after the function returns. This is why we also call heap space free store. However, it must be remembered that the heap space occupied by the object can be released only once, which is established in the function, while releasing outside the function is easy to get out of control and often makes mistakes.
Programming learning - dynamic memory allocation - based on C + + classes
Heap objects and constructors
The constructor should be called for the object established through new, and the destructor should also be called for deleting the object through delete.

CGoods *pc;
pc=new CGoods;  //Allocate heap space and construct an anonymous
                               //CGoods object;
.......
delete pc;  //Destruct first, and then return the memory space to the heap;
    The lifetime of the heap object does not depend on establishing its scope, so the lifetime of the heap object (nameless object) will not expire unless the program ends, and it needs to be explicitly used delete Statement destructs the heap object, and the above heap object is executing delete Statement, C++Automatically call its destructor.
Because constructors can have parameters, so new Back class( class)Types can also have parameters. These parameters are the parameters of the constructor.
However, for creating an array, there are no parameters and only the default constructor is called. See the class description of the following example:
class CGoods{
           char Name[21];
           int  Amount;
           float Price;
           float Total value;
public:
  CGoods(){}; //Default constructor. Because there are other constructors, the system will not automatically generate the default constructor, which must be explicitly described.
  CGoods(char* name,int amount ,float price){
            strcpy(Name,name);
            Amount=amount;
            Price=price;
            Total_value=price*amount;  }
            ......
};//End of class declaration
//Note how to use:
void main(){
  int n;
  CGoods *pc,*pc1,*pc2;
  pc=new CGoods("Xiali 2000 ", 10118000);
  //Call the three parameter constructor
  pc1=new CGoods();  //Call default constructor
  cout<<'Enter the number of elements of the commodity class array'<<endl;
  cin>>n;
  pc2=new CGoods[n];
 //Dynamically create an array and cannot be initialized. Call the default constructor n times
  ......
  delete pc;
  delete pc1;
  delete []pc2;  }

This example tells us how to use heap objects:
After applying for heap space, the constructor runs;
The destructor runs before freeing heap space;
Again, when creating an object array from the heap, you can only call the default constructor, not any other constructor. If there is no default constructor, you cannot create an object array.

Topics: C++ C#