动态内存分配malloc/free/new/delete的几个关键问题及解答
1.为啥在C++要引入new/delete运算符
相比与malloc仅仅是分配动态的内存,new提供了调用对象的构造函数的机制,new/delete是C++引入的可以完全替代malloc/free来进行动态内存使用的机制,此外,new/delete具备内存空间大小的自动计算,类型检查,比malloc/free更加安全;
2.new的重载版本及使用
//一般new的使用,即失败可以抛出异常版本
int * p_1 = new int(123);
//不抛出异常的new
int *p_2 = new(nothrow) int(123);//失败则返回nullptr
//placement new,可以重分配的new
//基于已经分配的内存,进行对象构造
char * p_or = new(nothrow) [sizeof(Your_Classtype)];
if(p_or==nullptr){
cout<<"faild"<<endl;
}
Your_Classtype *p_3 = new(p_or) Your_Classtype;
//析构时有所不同
//1.显示调用析构
p_3->~Your_Classtype();
delete p_or;
3.new申请,free释放会导致的问题
最明显的问题就是new分配的对象,delete释放,可以调用析构函数,而若在析构函数中,涉及到一点关键资源,例如使用了动态内存,free由于没有调用对象的析构函数,会导致资源泄露。
4.malloc/free底层原理
new/delete是对malloc/free的封装,而malloc/free是对brk,mmap等系统调用的封装;
brk:维护一个指向堆顶部的一个指针,单malloc分配的内存小于128K时,通过将堆顶指针向高地址移动,实现动态内存分配;
mmap:但malloc请求的内存大小大于128K时,从堆跟栈之间的文件映射区找一块大小符合申请需求的虚拟内存进行分配;
brk跟mmap的区别:brk释放内存时,需要等高地址部分被释放了,才能释放地地址部分。而mmap的释放是独立的。
5.new/delete在单个简单对象,单个复杂对象,简单类型动态数组,复杂类型动态数组分配时的不同。
对于单个对象:
简单的:直接调用operator new分配内存;
复杂的:先使用operator new分配原始的,未初始化的内存,随后调用构造函数进行对象构造;
对于动态数组:
简单的:
new[]计算好大小后,多次调用operator new();
复杂的:
先调用operator new[]分配多个内存,随后在前四个字节记录分配的动态数组的大小,继而调用n次构造函数,最后返回p-4处的地址值。