前言:在C语言中,我们开辟空间时,通常使用malloc、free 和 realloc 等进行空间开辟,在C++中,我们也可以使用C语言中的方法,但是有些地方就会比较麻烦,所以C++就提出了自己的内存管理方法:通过 new 和 delete 操作符来进行动态内存开辟管理。
C++动态内存管理
new/delete 操作内置类型
void Test ()
{//动态申请一个int类型的空间int* ptr1 = new int ;// 动态申请一个int类型的空间并初始化为1int* ptr2 = new int (1);//动态申请10个连续的int类型的空间int* ptr3 = new int [10];delete ptr1;delete ptr2;delete[] ptr3;
}
- 申请和释放单个元素空间使用的是 new 和 delete 操作符
- 申请和释放一段连续的空间时,使用的是 new[ ] 和 delete[ ]
new/delete操作自定义类型
class Test
{public:Test(): _data(0){cout<<"Test():"<<this<<endl;}~Test(){cout<<"~Test():"<<this<<endl;}private:int _data;
};int main()
{// 申请单个Test类型的空间Test* p1 = (Test*)malloc(sizeof(Test));free(p1);// 申请10个连续Test类型的空间 Test* p2 = (Test*)malloc(sizoef(Test) * 10);free(p2);// 申请单个Test类型的对象Test* p3 = new Test;delete p3;// 申请10个连续的Test类型的对象Test* p4 = new Test[10];delete[] p4;
}
- 在申请自定义类型的空间时,new 会调用构造函数,delete 会调用析构函数,而 malloc 和 free 不会调用对应的构造和析构函数
-
Test* p1 = (Test*)malloc(sizeof(Test));Test* p3 = new Test;在ANSI C标准中,malloc() 返回值类型是 void* ,malloc 并不知道返回的类型,所以需要用户自己定义,所以在使用时就要进行强制类型转换。 而 new 不需要进行强制类型转换,在开辟完空间后,它会调用构造函数完成对象的构造。
new/delete执行原理
内置类型
内置类型的空间开辟,malloc free 与 new delete 基本一致,不同之处在于
- new/delete申请单个元素空间,new[]/delete[]申请连续空间
- malloc 在申请空间失败返回NULL指针,而new申请失败时,会抛出异常
自定义类型
new的原理
- 申请空间:调用 operator new 函数
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)//size:new之后所跟类型的字节数{ // try to allocate size bytesvoid *p;while ((p = malloc(size)) == 0)//返回失败if (_callnewh(size) == 0)//检测用户是否提供内存空间不足的应对方式{ // report no memory// 如果申请失败,就会抛出 bad_alloc 类型异常_THROW_NCEE(_XSTD bad_alloc, );}return (p);//成功直接返回}
operator new 函数内部使用 malloc 实现
- 申请成功,直接返回开辟的空间的首地址
- 申请失败,检测用户是否提供内存空间不足的应对方式。如果提供,执行用户所给的内存空间不足的解决方案,然后继续申请空间;如果不提供,就抛出异常
- 调用相应的构造函数完成对象的构造
delete的原理
- 在空间上调用析构函数,完成对象中资源的清理工作
- 释放空间:调用 operator delete 函数
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_FINALLYreturn;
}
本质上是使用 free 来进行释放
new T[N]的原理
- 申请空间:调用 operator new[ ] 函数
void * operator new[]( size_t cb )
{void *res = operator new(cb);RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));return res;
}
内部使用 operator new (size)函数实现,该函数还是用 malloc 来实现
- 调用构造函数对N个对象进行初始化
delete [] 的原理
- 调用N次析构函数,将对象中的资源清理干净(顺序:从后往前)
- 调用 operator delete [ ] (void *p)
void operator delete[](void * pUserData, int, const char *, int) {::operator delete[](pUserData); }内部实现是 operator new (p),该函数内部还是用 free 来实现