new源代码如下
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);
}
new运行会用两步
- 调用malloc函数分配空间,进行判断是否分配成功,如果成功执行第二步,否则调用代码
static const std::bad_alloc nomem;
_RAISE(nomem);
这个是用户提供的空间不足的应对方法,如果用户没有提供这里会抛出异常,如果提供运行完后,会再判断一次是否malloc成功。
2. 调用构造函数
delete代码如下
void operator delete(void *pUserData)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return;
}
delete运行两步
- 调用析构函数将实例内的资源释放
- 调用operator delete函数 , 这个函数调用free函数释放实例。
new[]和delete[]的使用方法和上面的类似,但是有一个问题,new[]是用来分配n个元素的,例如
Test *ptr = new Test[10];
delete[]时怎么确定调用几次析构函数。
原因是因为C++的做法是在分配空间时多分配了4个字节的空间用来存储次数。
所以我们知道
-
delete[]调用的析构函数次数是从前4个字节里取出来
-
传入operator delete[]的参数ptr不是指针的指,而是指针减4的指
如果分配的是内置数据类型,就不需要储存次数,new[] delete是可以的,但是如果是自定义类型会导致两个情况 -
只调用了一次析构函数,调用了一次operator delete[]造成内存泄漏
2.直接释放传入的参数指向的空间,但是new[]的参数指向的空间前4个储存的是个数 ,正确的释放空间时传入的参数指向的空间减4,这样会导致程序崩溃。
记住一点,new/delete new[]/delete[]要配套使用。