Dynamic memory management in C++ (implementation of new/delete)

1. Review dynamic memory management in C language

C language dynamic memory management

2. C++ memory management method

The C language memory management method can continue to be used in C++, but in some places it is powerless and cumbersome to use. Therefore, C++ proposes its own memory management method: dynamic memory management through the new and delete operators.

2.1 new/delete code demo:

int main()
{
    
    
	//申请单个类型的空间
	int* p1 = new int;

	//申请单个类型空间,并且对空间中的内容进行初始化
	int* p2 = new int(10);

	//申请一段连续的空间
	int* p3 = new int[10];

	//申请一段连续的空间,并进行初始化
	int* p4 = new int[10]{
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

	//使用delete来释放单个空间
	delete p1;
	delete p2;

	//使用delete[]来释放连续的空间
	delete[] p3;
	delete[] p4;
	return 0;
}

Note : To allocate and release space for a single element, use the new and delete operators, and to allocate and release contiguous space, use new[] and delete[].

2.2 new and delete operation custom type

class Test
{
    
    
public:
	Test(int t)
		: _t(t)
	{
    
    
		cout << "Test():" << this << endl;
	}
	~Test()
	{
    
    
		cout << "~Test():" << this << endl;
	}
private:
	int _t;
};

int main()
{
    
    
	//注意:如果类带有无参或者全缺省的构造函数时,new类类型对象时,可以不带参数
	//      如果类具有带有参数的构造函数时,new类类型对象时,必须带参数
	Test* pt1 = new Test(10);
	Test* pt2 = new Test(20);
	delete pt1;
	delete pt2;
	return 0;
}

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

3. operator new and operator delete functions

new and delete are the 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 the space. .

3.1 operator new function

/* operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败, 尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。 */ 
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) 
{
    
        
    // try to allocate size bytes    
    void *p;    
    while ((p = malloc(size)) == 0)        
        if (_callnewh(size) == 0)        
        {
    
                
            // report no memory            
            // 如果申请内存失败了,这里会抛出bad_alloc 类型异常            
            static const std::bad_alloc nomem;            
            _RAISE(nomem);       
        }
 
    return (p); 
}

Operator new actually applies for space through malloc. If the malloc application space is successful, it returns directly. Otherwise, the user-provided measures for insufficient space are executed. If the user provides such measures, the application continues, otherwise an exception is thrown.

3.2 operator delete function

/* operator delete: 该函数最终是通过free来释放空间的 */ 
void operator delete(void *pUserData) 
{
    
            
        _CrtMemBlockHeader * pHead;
        RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
        if (pUserData == NULL)
            return;
         _mlock(_HEAP_LOCK);  /* block other threads */            
         __TRY
        /* get a pointer to memory block header */            
        pHead = pHdr(pUserData);
        /* verify block type */            
        _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
        _free_dbg( pUserData, pHead->nBlockUse );
        __FINALLY            
        _munlock(_HEAP_LOCK);  /* release other threads */        
        __END_TRY_FINALLY
        return; 
}

/* free的实现 */
 #define   free(p)    _free_dbg(p, _NORMAL_BLOCK

operator delete finally frees space through free.

4. Implementation principle of new and delete

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

4.2 Principle of custom type 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

delete principle

  1. Execute the destructor on the space to complete the cleanup of resources in the object
  2. Call the operator delete function to free 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 requested space

The principle of delete[]

  1. Execute N 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 in operator delete[] to release space

5. Positioning new expressions (placement-new)

Positioning the new expression is to call the constructor to initialize an object in the allocated original memory space.

Usage scenario: The
positioning new expression is generally used with the memory pool in practice. Because the memory allocated by the memory pool is not initialized, if it is an object of a custom type, you need to use the definition expression of new to explicitly call the constructor for initialization.

class Test
{
    
    
public:
	Test(int t = 10)
		: _t(t)
	{
    
    
		cout << "Test(int t):" << this << endl;
	}
	~Test()
	{
    
    
		cout << "~Test(int t):" << this << endl;
	}
private:
	int _t;
};
int main()
{
    
    
	Test* pt = (Test*)malloc(sizeof(Test));
	new(pt) Test(100);

	free(pt);
	return 0;
}

6. The difference between malloc/free and new/delete

The common point of malloc/free and new/delete is that they both apply for space from the heap and need to be released manually by the user.
The difference is:

  1. malloc and free are functions, new and delete are operators
  2. The space applied by malloc will not be initialized, new can be initialized
  3. When malloc applies for space, you need to manually calculate the size of the space and pass it, and new only needs to follow the type of space.
  4. The return value of malloc is void*, which must be cast when used, and new is not needed, because new is followed by the type of space
  5. When malloc fails to apply for space, it returns NULL, so it must be empty when using it, new does not need it, but new needs to catch exceptions
  6. When applying for a custom type object, malloc/free will only open up space, and will not call the constructor and destructor, while new will call the constructor to complete the initialization of the object after applying for the space, and delete will call the destructor before releasing the space. Complete the cleanup of resources in the space

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324208290&siteId=291194637
Recommended