C++中new和delete的实现

本文详细介绍了C++中new和delete操作符的工作原理,包括内存分配、构造函数和析构函数的调用,以及new运算符在不同情况下的内存布局。特别地,讨论了new操作数组时如何存储元素个数,以及delete在释放数组时如何正确调用析构函数。此外,还分析了当类包含指针成员时,new和delete操作可能导致的内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • new和delete的实现
    在这里插入图片描述
    在这里插入图片描述
new
Class* pc = new Class(2,1); //即new等价于malloc + 构造函数;
等价于
void* mem = operator new(sizeof(Class)); //分配内存;相等于malloc
pc = static_cast<Class*>(mem); //类型转换;
pc->Class::Class(2,1); //pc调用构造函数,pc相当于this;
delete
string* s = new string("hello");
delete s; /*即等价于析构函数 + free(s);最终结果是释放了“hello”和s指向的string对象中的所有数据成员(即char* m_data)*/
等价于
string::~string(s); /*析构函数;上图中未给出string类的析构函数的实现,具体实现为释放s指向的string对象的数据成员指向的“hello”的内存;*/
operator delete(s);/*此函数底层调用的free(s),释放s指针指向的对象内存(此处s指向的是是仅有一个指针成员的string对象,因此free(s)会释放该指针数据成员本身的内存(即释放指针s指向的指针char* m_data);*/
  • new一个对象到底获得了多大内存
    以下讨论均为在编译器VC内的情况,可能不同编译器有些许区别;
Complex* p1 = new Complex(2,1); //此类内有两个double数据成员,共占4*2 = 8bite;若class Complex含有虚函数,则一个Complex对象大小是8 + 4 = 12bite;
String* p2 = new String("lixu");//此类只有一个指针数据成员char* m_data,占4bite;同上,若class String含有虚函数,则一个String对象大小为4+4=8bite;
  1. 类Complex只有一个指针数据成员,占4bite,即图中绿色部分是我们本意想要获得的内存;
  2. 上下各有一块红色的4字节的16进制cookie用于告知操作系统,cookie中间夹着的内存(包括红色内存块在内)是否被分配出去;最后两位16进制代表分配的总内存大小,由于一定是16的倍数,因此最后一位必定为0.所以可以用最后一位为1来表示内存已经分配出去,则操作系统不能再使用这块内存;若delete之后,该位变成0,则操作系统知道这块内存现在可以被重新使用或被覆盖等等;如第一个为41,代表内存大小为64,且这块内存被分配出去了;
  3. 在调试模式下,(32位操作系统下)还会有灰色的:上面8块4bite内存,下面有一块4bite内存,即多出32+4;
  4. 若以上三者总内存不是16的倍数,则在绿色部分下面用蓝色部分补齐(一块4bite);
    在这里插入图片描述
  • 数组
Complex* p1 = new Comples[3];
delete [] p1; /new [],则delete[];

String* p2 = new String[3]; 
delete [] p2;
  1. 相比上图中的new单个变量,new数组的话,在我们本意需要分配的那块内存上面,还需多分配4bite的int值,用于存该数组的元素个数;如下面中第一个白色的3代表分配了3个Complex;操作系统就知道下面的6块double是代表3个元素;则在delete[ ] p1时,调用三次析构函数(delete的底层实现是析构函数+free),每次释放一个元素;
  2. 上下的51h,31h等,意思和上图一样,代表分配的内存大小,1代表内存被分配出去了;末尾的h代表hex16进制;
    在这里插入图片描述
  3. 对于下图的String来说,因为它的数据成员为一个指针,因此如果不加[ ],直接delete p1的话,编译器只知道调用一次析构函数,则只把数组的第一个成员指向的字符串释放了(即数组中第一个指针指向的内存释放掉了,并不知道数组还有别的指针);接下来的operator delete(即底层的free)操作会根据上下的cookie中保存的整个内存块的大小,释放掉包括cookie在内的整块内存(即也成功释放掉了new获得的3个指针成员本身),但除了第一个指针以外,其余指针指向的内存都没有被释放!造成内存泄漏;即即使new[ ]搭配delete,由于内存中记录了元素个数,所以这些元素本身都会被释放掉,只是当元素本身存储的是指针(指向动态分配的内存的话),这些动态分配的内存只会被释放一块,后面的内存泄露;
    但对于Complex来说,因为它的数据成员为两个double而不是指针,所以即使不加[ ],直接delete p2的话,最终的结果也是没问题的;但好的习惯还是无论数组成员含不含指针,new[ ] 一定要搭配delete[ ]防止泄露;
    在这里插入图片描述
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值