C++内存管理—new、delete
1.new和delete
new的内部执行顺序:
[1]调用operator new函数,该函数里面调用malloc申请内存。
[2]调用类的构造函数。
delete的内部执行顺序:
[1]调用类的析构函数。
[2]调用operator delete函数,该函数里面调用free释放内存。
operator new和operator delete函数可以重载,这两个函数的声明在文件:/usr/include/c++/4.8.2/new。
2.new[]和delete[]
如果有显式的析构函数时,使用new[]申请内存时,会在前面多分配4个字节用来保存数组大小,在 delete[]的时候会依次逆序调用数组中各对象的析构函数;如果没有显式的析构函数时,使用new[]申请内存时,不会在前面多分配4个字节。
new[10]的内部执行顺序:
[1]先调用operator new[]函数,里面调用malloc分配4字节(有显式构造函数时) + 10个对象大小的内存。
[2]然后在前四个字节写入数组大小(有显式构造函数时)。
[3]最后调用10次构造函数。
delete[]的内部执行顺序:
[1]根据最前面的4个字节得到对象个数,调用n次类的析构函数。(有显式构造函数时)
[2]调用operator delete[]函数,里面调用free释放4字节(有显式构造函数时) + 10个对象大小的内存。
【1】如果是调用了A *p = new A[10];时:
如果此时没有显式的构造函数,则:不管是调用delete p;还是delete[] p;都会释放数组的内存。不同的是调用delete p,只会对第一个元素调用析构函数,但此时的析构函数是空函数(如果类中无析构函数,则编译系统会默认补上一个空的析构函数),因此也不会造成内存泄漏。
如果此时有显式的构造函数,则调用delete p时程序崩溃,因为p的前4个字节处才是申请内存的起始位置。
【2】如果是调用了A *p = new A;时:
如果此时没有显式的构造函数,则:不管是调用delete p;还是delete[] p;都会释放p的内存,并且都会调用一次A的析构函数(空函数)。
如果此时有显式的构造函数,则调用delete[] p时程序崩溃,因为这个会从p向前取4个字节作为元素个数,而申请时没有申请这4个字节。
因此,从上面的分析看,混用delete和delete[]只会导致程序可能崩溃,没有哪种情况会导致内存泄漏。