目录
前言:在C语言中,我们开辟空间时,通常使用malloc、free 和 realloc 等进行空间开辟,在C++中,我们也可以使用C语言中的方法,但是有些地方就会比较麻烦,所以C++就提出了自己的内存管理方法:通过 new 和 delete 操作符来进行动态内存开辟管理。
C++动态内存管理
new/delete 操作内置类型
void Test ()
{
//动态申请一个int类型的空间
int* ptr1 = new int ;
// 动态申请一个int类型的空间并初始化为1
int* 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 bytes
void *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_FINALLY
return;
}
本质上是使用 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 来实现