[C++] - memory management (new and delete)

1 Introduction

When learning C language, we learned dynamic memory management, that is, dynamically open up some memory on the heap for our use. Although the method of C language memory management can also be used in C++, there are still some places that he can't do anything about. , so let's learn how to manage C++ memory today.

2. C/C++ memory distribution

Before learning memory management, let's first understand what the program memory area in C/C++ is divided into.

1. The stack is also called the stack, which stores non-static local variables/function parameters/return values, etc., and the stack grows downward.
2. The memory-mapped segment is an efficient I/O mapping method for loading a shared dynamic memory bank. Users can use the system interface to create shared shared memory for inter-process communication.
3. The heap is used for dynamic memory allocation when the program is running, and the heap can grow upwards.
4. The data segment stores global data and static data.
5. Code segment, which stores executable code/read-only constants.

3. C language dynamic memory management

Dynamic memory management in C language relies on four functions: malloc, realloc, calloc, and free. The
specific functions of these functions can be found in the C language dynamic memory management article published by the blogger before, with detailed explanations

void Test()
{
    
    
	int* p1 = (int*)malloc(sizeof(int));
	free(p1);
	int* p2 = (int*)calloc(4, sizeof(int));
	int* p3 = (int*)realloc(p2, sizeof(int) * 10);
	//这里不需要free(p2)
	free(p3);
}

int main()
{
    
    
	Test();
	return 0;
}

4. C++ memory management method

The C language memory management method can continue to be used in C++, but it is powerless in some places, and it is more troublesome to use, so C++ has proposed its own memory management method: dynamic memory management through new and delete operators.

However, new and delete have different processing methods for built-in types and custom types. Let's learn how new and delete handle built-in types and custom types respectively.

4.1 Built-in types

For built-in types, there is no essential difference between new/delete and malloc/free, only the difference in usage, and the usage of new/delete is simplified.

Below we directly illustrate the use of new and delete for built-in types.

void Test()
{
    
    
	//C语言
	//动态申请一个int类型的空间
	int* p1 = (int*)malloc(sizeof(int));

	//C++
	//动态申请一个int类型的空间
	int* p2 = new int;
	//申请5个int的数组
	int* p3 = new int[5];

	//申请1个int对象,初始化为5
	int* p4 = new int(5);

	//C++11支持new[] 用{}初始化  C++98不支持
	int* p5 = new int[5]{
    
    1,2,3};

	//C语言
	free(p1);

	//C++
	delete p2;
	delete[] p3;
	delete p4;
	delete[] p5;
}

int main()
{
    
    
	Test();
	return 0;
}

Note : To apply for and release the space of a single element, use the new and delete operators to apply for and release continuous space, and use new[] and delete[], which must be matched.

4.2 Custom types

When applying for a custom type of space, new will call the constructor, delete will call the destructor, but malloc and free will not.

For example:

class A
{
    
    
public:
	A(int a = 0)
		:_a(a)
	{
    
    
		cout << "A():" << this << endl;
	}

	~A()
	{
    
    
		cout << "~A():" << this << endl;
	}

private:
	int _a;
};


int main()
{
    
    
	//C语言
	//malloc
	//在堆上申请空间
	A* p1 = (A*)malloc(sizeof(A));
	if (p1 == NULL)
	{
    
    
		perror("malloc fail\n");
		return 0;
	}

	//释放空间
	free(p1);

	//C++
	//new
	//在堆上申请空间、调用构造函数初始化
	//A* p2 = new A;
	A* p3 = new A(10);

	//调用析构函数清理对象中的资源、释放空间
	delete p3;

	return 0;
}

insert image description here

Summary : The biggest difference between new/delete and malloc/free is that new/delete not only opens up space for custom types, but also calls constructors and destructors, which are almost the same for built-in types.

5. operator new and operator delete functions

new and delete are operators for users to apply and release dynamic memory.
operator new and operator delete are global functions provided by the system.
New calls the operator new global function at the bottom layer to apply for space, and delete uses the operator delete global function at the bottom layer to release space.

operator new:
This function actually uses malloc to apply for space. When malloc successfully applies for space, it returns directly. When the space application fails, it tries to implement the countermeasures for insufficient space. abnormal.

operator delete:
This function finally releases space through free.

6. Implementation principle of new and delete

Built-in type :
If you are applying for a built-in type of space, new and malloc, delete and free are basically similar.
The difference is:
new/delete applies for and releases the space of a single element, new[] and delete[] apply for and release continuous space, and new will throw an exception when the application space fails, and malloc will return NULL.

Custom type :
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 cleanup of resources in the object
2. Call the operator delete function to release the space of the object
The principle of 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 the constructor N times on the applied space
The principle of 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 delete function in operator delete[] to release space

7. Position new expression (placement-new)

Positioning the new expression is to call the constructor to initialize an object in the allocated original memory space.
Usage format :
new (place_address) type or new (place_address) type(initializer - list)
place_address must be a pointer, and initializer - list is the initialization list of the type
Usage scenario :
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.

class A
{
    
    
public:
	A(int a = 0)
		: _a(a)
	{
    
    
		cout << "A():" << this << endl;
	}

	~A()
	{
    
    
		cout << "~A():" << this << endl;
	}

private:
	int _a;
};

int main()
{
    
    
	A* p1 = new A;

	A* p2 = (A*)malloc(sizeof(A));
	if (p2 == nullptr)
	{
    
    
		perror("malloc fail");
		return 0;
	}

	//new(p2)A;
	new(p2)A(10);

	return 0;
}

8. Ending

We have learned the way of C++ memory management here. After learning new and delete, we will try to use new and delete in the future, because new and delete are not only much simpler than malloc and free, but also more practical and intelligent.
Finally, I would like to thank you for your patient reading and support. Friends who think this article is well written can follow and support it three times. If you have any questions or there are mistakes in this article, you can private message me or leave a message in the comment area Discussion, thanks again everyone.

Guess you like

Origin blog.csdn.net/qq_43188955/article/details/130786108