一、new[]数组
- new[]也分为两种情况:
- 1、简单数据类型( 包括基本数据类型和不需要析构函数的类型)。
new[] 调用的是operator new[],计算出数组总大小之后调用operator new。
值得一提的是,可以通过()初始化数组为零值,实例:char* p = new char[32]();
等同于:char *p = new char[32]; memset(p, 32, 0);
总结:
针对简单类型,new[]计算好大小后调用operator new。
2、复杂数据类型(需要由析构函数销毁对象)
实例:class Object { public: Object() { _val = 1; } ~Object() { cout << "destroy object" << endl; } private: int _val; }; void main() { Object* p = new Object[3]; }
new[]先调用operator new[]分配内存,然后在p的前四个字节写入数组大小,最后调用三次构造函数。
实际分配的内存块如下:
这里为什么要写入数组大小呢?因为对象析构时不得不用这个值。
释放内存之前会调用每个对象的析构函数。但是编译器并不知道p实际所指对象的大小。如果没有储存数组大小,编译器如何知道该把p所指的内存分为几次来调用析构函数呢?
总结:
针对复杂类型,new[]会额外存储数组大小。
二、delete数组
delete[]也分为两种情况:
1,简单数据类型( 包括基本数据类型和不需要析构函数的类型)。
delete和delete[]效果一样
比如下面的代码:
int* pint = new int[32]; delete pint; char* pch = new char[32]; delete pch;
运行后不会有什么问题,内存也能完成的被释放。看下汇编码就知道operator delete[]就是简单的调用operator delete。
总结:
针对简单类型,delete和delete[]等同。
2,复杂数据类型(需要由析构函数销毁对象)
释放内存之前会先调用每个对象的析构函数。
new[]分配的内存只能由delete[]释放。如果由delete释放会崩溃,为什么会崩溃呢?
假设指针p指向new[]分配的内存。因为要4字节存储数组大小,实际分配的内存地址为[p-4],系统记录的也是这个地址。delete[]实际释放的就是p-4指向的内存。而delete会直接释放p指向的内存,这个内存根本没有被系统记录,所以会崩溃。
总结:
针对复杂类型,new[]出来的内存只能由delete[]释放。