delete与delete[]以及堆内存分配的一点说明

1. 简述

    本文主要说明两点,第一,对于基本数据类型,delete和delete[]在释放数组上是一样的,至少结果上看是一样的。第二,堆内存地址分配大多数情况是无法预测的,而栈是更容易预测。

2. delete与delete[]   

#include <iostream>
using namespace std;
class AK {
public:
  AK() { 
    cout 
<< "make one ak" << endl;
  }
  
~AK() {
    cout 
<< "destroy one ak" << endl;
  }
};
int main() {
    
int *= new int[10];
    cout 
<< (size_t)p << endl; // 输出4013520
    delete p;
    // delete []p;
    p 
= new int[10];
    cout 
<< (size_t)p << endl; // 输出4013520
    delete[] p;
    p 
= 0;
    
//-------------------------
    AK 
*pAK = new AK[10];        // 输出10次“make one ak”
    cout 
<< (size_t)pAK << endl; // 输出4013572
    delete pAK;                  // 输出1次“destroy one ak”
    pAK = new AK[1000000000];    // 输出10次“make one ak”
    cout 
<< (size_t)pAK << endl; // 输出4013596
    delete []pAK;                // 输出10次“destroy one ak” 

    system("PAUSE");
    
return 0;
}

      指针p存储在栈中,开辟的空间在堆中,第一次,开辟的空间地址为4013520,用delete释放数组后,第二次,重新开辟,空间地址还是4013520。这说明,delete对于int数组的释放是同样有效的。
     指针pAK存储在栈中,开辟的空间在堆中,第一次开辟的空间地址为 4013572,用delete释放数组后,第二次,重新开辟,空间地址为4013596。说明原来的空间没有完全释放掉,原因就是第一次用delete只调用了一次析构函数,即输出了1次“destroy one ak”。

3. 堆地址的预测难度很大   

#include <iostream>
using namespace std;

int main() {
    
int*= new int;
    
int*= new int;
    cout 
<< (size_t)a << endl; // 输出4013416
    cout 
<< (size_t)b << endl; // 输出4013520
    system(
"PAUSE");
    
return 0;
}

     a,b两个int*存储在栈上,开辟两个int存储在堆中,堆中两个int的地址竟然相差了104个字节。一般如果是栈的话,两个连续定义的int,其地址肯定是连续的。
     原因是堆的实现结构是链表,每次都从链表头开始扫描,找到能够满足需要的内存块就返回,剩余的小块继续放回链表,当有内存释放,再融入链表,因此堆是存在碎片的,而栈是顺序的存储结构,不存在碎片这一说,因此堆中的地址是很难预测的。堆的链表是管理结构,对于动态开辟内存十分适合,不过这也是其地址不好预测的原因之一。一种情况例外,即开辟几个对象,然后把这几个对象都释放掉,再按照相同的顺序开辟相同的对象,对应的地址是相同的。比如:分别开辟int,char,int[10],然后把他们都释放掉,再顺序的开辟int, char, int[10],对应的地址肯定是相同的,因为释放掉以后,链表恢复了原来的情况。

4. 总结

    · 对于基本数据类型数组delete与delete[]一样,对于子定义的类型数组,只有delete[]可以。
    · 堆是一种链表式存储结构,大多数情况下,使用其开辟的数据无法预测。

5. 感慨

    delete,new,delete[],new[]这些操作符,不知道它们究竟是如何具体实现的,因此,很难真的理解为什么delete对基本数据类型数组也是可行,对自定义对象数组是不可行。不过呢,网上的文章看了很多,也没发现有讲出来的,也不纠结了,毕竟,C++很多都是人家隐藏好了,就是为了让你省事,如果不开发驱动级别或者系统级别程序的话,一般还真用不上。
    本文介绍的这些都有一个特点,就是知道这些和不知道这些,对使用没什么大的区别,该new与delete对应还是对应,也没人没事找堆中开辟空间的地址,不过以后再看C++代码的时候,距离真相可能更近了一步,仅此而已。

6. 参考

    delete与delete[]的区别    http://hi.baidu.com/shijg/blog/item/f1b24d16d4b4774920a4e987.html
    C++中delete与delete[]的区别    http://jazka.blog.51cto.com/809003/230220

posted @ 2011-08-11 10:49  xiaodongrush  阅读(415)  评论(0编辑  收藏  举报