#|C++ new/delete和new[ ]/delete[ ] 深入解析


在C语言中,用malloc/free 从堆里面动态申请出来一段内存。但对这一块申请出来的内存,往往还需要对它进行初始化 。虽然C语言提供了calloc来开辟一段初始化好(0)的内存,但面对各式各样的数据成员初始化,它同样束手无策。同时,为了保持良好的编程习惯,应该对申请出来的内存手动进行初始化。
在C++中有了new/delete, new []/delete[] ,用它们便可较方便地实现动态的内存管理。
一、new/delete, new []/delete []初始化

int* p1=new int; //动态分配4个字节(1个int)的空间单个数据 int* p2=new int(3); //动态分配4个字节(1个int)的空间,并初始化为3 int* p3=new int[3]; //动态分配12个字节(3 个int)的空间 delete p1; delete p2; delete[] p3;

new/delete动态管理对象,new[]/delete[]动态管理对象数组
在C++中,把int 、char..等内置类型的变量也看作对象,它们也是存在构造函数和析构函数的,只是通常对它们,系统调用了默认的构造函数来初始化以及默认的析构(编译器优化)。所以new int、new int(3)看起来和普通的定义好像没什么区别。 但对于自定义类型的对象,此种方式在创建对象的同时,还会将对象初始化好;于是new/delete、new []/delete []方式管理内存相对于malloc/free的方式管理的优势就体现出来了,因为它们能保证对象一被创建出来便被初始化,出了作用域便被自动清理。
二、malloc/free和new/delete的区别
malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间还会调用构造函数和析构函数进行初始化与清理(清理成员)。
它们都是动态管理内存的入口。
malloc/free是C/C++标准库的函数,new/delete是C++操作符。
malloc/free需要手动计算类型大小且返回值为void*,new/delete可自动计算类型的大小,返回对应类型的指针。
malloc/free管理内存失败会返回0,new/delete等的方式管理内存失败会抛出异常。
三、new/delete的真正调用
尽管看起来new、new[] 和malloc 都能开得空间出来,并且以new 、new[]的方式好像还更有优势。但从系统层面看来,真正开出空间来的还是malloc。为什么这么说呢?
在C++ Primer书中有提到说: new/delete的表达式与标准库函数同名了,所以系统并没有重载new或delete表达式。new/delete真正的实现其实是依赖下面这几个内存管理接口的。c++中称之为“placement版”内存管理接口
void * operator new (size_t size); void operator delete (void* ptr,size_t size); void * operator new [](size_t size); void operator delete[] (void* ptr,size_t size);

代码实现:
#include #include #include using namespace std; class Test { int val; double t; public: Test(const int val):val(val){} Test(void) { cout<<"构造函数"<

delete[]实际做了这样几件事情:
1、依次调用pA指向对象数组中每个对象的析构函数,共n次
2、调用operator delete[](),它将再调用operator delete
3、底层用free执行operator delete表达式,依次释放内存
那么编译器怎么知道要释放几次?
new最后将开辟好内存用指针p返回,在它之前用4个字节来保存一个东西——对象个数,即n。这也就不难解释 为什么在delete[] 的时候,不用传给它对象个数。
delete[] 删除时,将new[] 返回的地址再往前移4个字节便可以拿到要析构的对象个数了。
注意:new type[] ,只有type显示定义析构函数时,编译器才会多开4字节来保存对象个数。所以像new int、char这样的内置类型编译器不会多开这4字节,编译器自行优化
【#|C++ new/delete和new[ ]/delete[ ] 深入解析】new/delete、new[]/delete[] 要配套使用!!!

    推荐阅读