operator new与operator delete函数(重点)
new delete 实现原理
1. 内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是new delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常。malloc返回NULL
2.自定义类型
* new原理
1.调用operator new函数申请空间
2.在申请的空间上执行构造函数,完成对象的构造*new Array[N]的原理
1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
2.在申请的空间上执行N构造函数*delete原理
1.在空间上执行析构函数,完成对象中资源的清理工作
2.调用operator delete数释放对象的空间*delete[]原理
1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2.调用operator delete[]放空间,实际在operator delete[]中调用operator delete释放空间
new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
class A
{
public:
A()
{
cout << "A()" << endl;
}
~A()
{
_a = 0;
cout << "A()" << endl;
}
private:
int _a;
}
int main()
{
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A;
A* p3 = (A*)operator new(sizeof(A));
size_t size =2;
void* p4 = malloc(size *1024*1024*1024*1024);
cout << p4 << endl;
void* p5 = operator new(size *1024*1024*1024*1024);
cout << p5 << endl;
operator delete(p5);
try{
void* p6 = operator new(size *1024*1024*1024*1024);
cout << p6 << endl;
}
catch(exception& e)
{
cout << e.what() << endl;
}
return 0;
}
当p4申请空间过大失败会返回0
当p5申请空间过大失败会抛异常
如果尝试p6这种方法try catch会怎么样呢?bad allocation - 错误分配
总结:malloc和operator new使用方式都一样,处理错误的方式不一样 可以用try catch 抛出异常
malloc/free operator new/operator delete new delete 这三者有什么区别呢?
operator new ==> malloc+失败抛异常实现
new ==> operator new + 构造函数
new比起malloc一样的地方:1、调用构造函数初始化 2、失败了抛异常 delete比起free一样的地方:1、调用析构函数清理
operator delete和 free区别,因为释放空间失败直接终止进程。 是因为要跟operatornew对出现才产生
operator new 他的底层函数是这样的
void* __CRTDECL operator new (size_t size) _THROW(_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 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;
}
通过上述两个全局函数的实现知道,operator new际也是通过malloc申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete终是通过free释放空间的。
定位new达式(placement-new)(了解)
定位new达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:
new(place_address)type或者new(place_address)type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new定义表达式进行显示调构造函数进行初始化。
class A
{
public:
A(int a=0)
:_a(a)
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()"<< endl;
}
private:
int _a;
};
int main()
{
A* p1 =new A;
delete pl;
// 想模拟上面的行为
//显示调用了A构造函数和析构函数
A*p2=(A*)operator new(sizeof(A));
// 对已经存在的一块空间调用构造函数初始化,定位new/replacement new
new(p2)A(10); //new空间的指针)类型(参数)参数不是必须
p2->~A();
operator delete(p2);
return 0;
}
常见面试题
malloc/free和new/delete的区别
内存泄漏
什么是内存泄漏,内存泄漏的危害?
内存泄漏分类(了解)
如何检测内存泄漏(了解)
如何避免内存泄漏
如何一次在堆上申请4G的内存?