C/C++ dynamic memory management, new and delete

 

Table of contents

C++ dynamic memory management

Dynamic memory management for built-in types

Dynamic memory management for custom types

Implementation principle of new and delete

The similarities and differences between new and malloc, delete and free

Other uses of new: positioning new


C language dynamic memory management <- click here

C++ dynamic memory management

Because the management method in C language is inconvenient to use and cannot solve the problem in some cases, C++ implements dynamic memory management through new and delete keywords. delete and new must be used together, and free can be used to free up space instead of new.


Dynamic memory management for built-in types

//动态申请1个int类型的空间
int* p1 = new int;
delete p1;

//动态申请1个int类型的空间并初始化为10
int* p2 = new int(10);
delete p2;

//动态申请10个int类型的空间
int* p3 = new int[10];
delete[] p3;

//动态申请10个int类型的空间并初始化
int* p4 = new int[10]{
    
    1,2,3,4,5,6,7,8,9,10};
delete[] p4;

//动态申请一个10行10列的二维数组
//int(*p)[n] 是一个数组指针,该数组有10个int类元素
int(*arr1)[10] = new int[10][10];
delete[] arr1;

//用二级指针模拟实现10行10列的二维数组
//内存开辟
int** arr2 = new int*[10];
for (int i = 0;i < 10;i++)
{
   arr2[i] = new int[10];
}
//空间释放
for (int i = 0;i < 10;i++)
{
    delete[] arr2[i];
}
delete[] arr2;

To apply and release space for a single element use new and delete, to apply and release continuous space use new[] and delete[]


Dynamic memory management for custom types

After allocating space for the custom type, new will call the constructor, and delete will call the destructor before releasing the space of the custom type

class Stack
{
private:
    int* _arr;
    int _capacity;
    int _top;
public:
    Stack()
        :_capacity(4)
        ,_top(0)
    {
        _arr = new int[4];
    }
    Stack(int capacity)
        :_capacity(capacity)
        ,_top(0)
    {
        _arr = new int[capacity];
    }
    ~Stack()
    {
        delete[] _arr;
    }
};

int main()
{
    Stack* st1 = new Stack(10);
    delete st1;
    Stack* st2 = new Stack[3];
    delete[] st2;
    Stack* st3 = new Stack[3]{ 5,2,4 };
    delete[] st3;
    Stack* st4 = new Stack[3]{ Stack(5),Stack(2),Stack(4) };
    delete[] st4;
}

Note: There are many ways to initialize an array of custom types. If there is a single-parameter constructor or a constructor with only one parameter except the default parameter, the array initialization can directly use the value of the parameter type and initialize it directly in { }, because It is automatically converted to an object to initialize the array; it can also be initialized with an anonymous object.


Implementation principle of new and delete

Because the function of malloc and calloc is to open up space, if it fails to open up space, return 0. But for the C++ object-oriented language, exceptions are often thrown when encountering problems, so operator new is used to encapsulate malloc to achieve the function of throwing exceptions. The same is true for operator delete.

The principle of new
1. Call the operator new function to apply for space
2. Execute the constructor on the applied space to complete the construction of the object
The principle of delete
1. Execute the destructor on the space to complete the cleaning of resources in the object
2. Call the operator
The principle of the delete function to release the object space new T[N]
1. Call the operator new[] function, and actually call the operator new function in operator new[] to complete the application of N object
spaces
2. Execute N on the applied space
The principle of secondary constructor delete[]
1. Execute N times of destructors on the released object space to complete the cleanup of resources in N objects
2. Call operator delete[] to release space, and actually call operator in operator delete[] delete to free
up space


The similarities and differences between new and malloc, delete and free

The same point: new and malloc, delete and free all apply for space from the heap, and all need to manually release the space

difference:

  • (Feature) new/delete is a keyword, malloc/free is a function
  • (Feature) When using malloc, it needs to calculate the size of the space, and new will automatically calculate it according to the data type. If there are multiple data, just specify the number directly in [ ].
  • (Features) The return value of malloc is void*, which requires mandatory type conversion when used, but new does not.
  • (feature) malloc fails to apply for space and returns NULL, while new needs to catch exceptions
  • (Function) The space applied by malloc will not be initialized, but the space applied by new can be initialized
  • ( Most important ) (Function) malloc/free will only open up and release space, while new will first call operator new to open up space and then call constructor initialization, delete will first call destructor to clean up space resources and then call operator delete to release space .

Other uses of new: positioning new

Function: Call the constructor initialization in a space that has been opened up

格式:new(address)custom type(initial list)或者new(address)basic type(initial list)

address is the address of the opened space;

custom type represents a custom type;

initial list represents the initialization list of the custom type;

basic type represents the basic data type

scenes to be used:

Positioning new expressions are generally used in conjunction with memory pools in practice. Because the memory allocated by the memory pool is not initialized, if it
is an object of a custom type, it needs to use the definition expression of new to explicitly call the constructor for initialization.

Advantage:

The application and release of memory has a certain amount of overhead. When you need to frequently apply for the release of memory, you can open the space at one time and use positioning new to call the constructor to initialize, which can improve efficiency.

class Date
{
    friend ostream& operator<<(ostream& _cout, const Date& d);
private:
    int _year;
    int _month;
    int _day;
public:
    Date(int year = 2023, int month = 1, int day = 1)
        :_year(year),
        _month(month),
        _day(day)
    {}
    ~Date()
    {}
};

//流插入运算符重载
ostream&  operator<<(ostream& _cout,const Date& d)
{
    _cout << d._year << "-" << d._month << "-" << d._day;
    return _cout;
}

int main()
{
    //基本数据类型
    int i = 5;
    int* p1 = (int*)malloc(sizeof(int));

    new(p1)int(10);
    cout << *p1 << endl;//10

    new(p1)int(i);
    cout << *p1 << endl;//5

    free(p1);

    //自定义数据类型
    Date* p2 = (Date*)malloc(sizeof(Date));

    new(p2)Date();//无参时,初始化的()可加可不加
    cout << *p2 << endl;//2023-1-1

    new(p2)Date(2023, 5, 20);
    cout << *p2 << endl;//2023-5-20

    p2->~Date();
    free(p2);
}

Guess you like

Origin blog.csdn.net/weixin_74269833/article/details/131004813
Recommended