#知错就改#delete和delete[]区别(转)

~~先讲讲delete到底是干什么的?~~

 

 1 #include <iostream>
 2 using namespace std;
 3 int main() 
 4 {
 5     int *p=new int; 
 6     *p=3;
 7     cout<<"将3赋给p的地址后,指针p读取的值:"<<*p<<endl;
 8     delete p;
 9     cout<<"删除空间后,指针p读取的值:"<<*p<<endl;
10     long *p1=new long;
11     *p1=100;
12     cout<<"创建新空间后,指针p中保存的地址:"<<p<<endl;
13     cout<<"指向新空间的指针p1保存的地址:"<<p1<<endl;
14     *p=23;
15     cout<<"将23赋给p的地址后,指针p读取的值:"<<*p<<endl;
16     cout<<"将23赋给p的地址后,指针p1读取的值:"<<*p1<<endl;
17     delete p1;
18     return 0;
19 }

 

从监视窗口中,我们可以看见虽然程序的第8行已经将指针p删除了,但是在监视窗口中p仍然存在,只是*p所指向的值不再是原来的3了,而是一个随机数。这里就说明了一个非常重要的概念:我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身

      然后我们接着往下分析。在程序的第10行我们又创建了一个long型的指针p1。在12行与13行的输出中我们惊奇地发现,指针p保存的地址居然和指针p1保存的地址一模一样!这个就说明了指针p和指针p1都指向内存的同一个地方!!!出现这种状况的原因其实是由于编译器。编译器默认将释放掉的内存空间回收然后分配给新开辟的空间。所以在第11行由于我们新开辟了一个可以保存long型变量的空间并且由p1来指向它,那么这里的p1指向的其实就是在程序第8行释放掉的内存空间,即p指向的内存空间!所以,这就导致了两个指针同时指向同一个内存空间。这是多不安全的一件事情啊!要知道,我们是把指针p删了的啊!如果再重新对*p进行赋值操作,那么不是会连着*p1一起改动么?

      果然,让我们担心的事情出现了。我们明明在程序的第11行中定义了*p1的值为100,但是在输出上面,指针p1读取的值竟然也是23。这个原因就是因为野指针p造成的。我们可以看到,在程序的第14行我们将23赋给了*p。又由于p和p1指向的是同一块内存单元,所以在这里相当于也将p1所指向的内存单元中的值(原来是100),改成了23!这样必然会导致程序的出错!

       那么我们就不禁要问了,对于这种由于野指针造成的问题,有没有解决的方法呢?答案当然是有的了。我们只需要牢记下面这句话:

在删除一个指针之后,一定将该指针设置成空指针(即在delete p之后一定要加上: p=NULL)

 

~~~delete和delete[]区别~~~

 

我们通常从教科书上看到这样的说明:

delete 释放new分配的单个对象指针指向的内存
delete[] 释放new分配的对象数组指针指向的内存


那么,按照教科书的理解,我们看下下面的代码:
int *a = new int[10];
delete a;        //方式1
delete [] a;     //方式2
肯定会有很多人说方式1肯定存在内存泄漏,是这样吗?

1. 针对简单类型 使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可 如:
   int *a = new int[10];
   delete a;
   delete [] a;
   此种情况中的释放效果相同 原因在于分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数,
   它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中 系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中,
   具体情况可参看VC安装目录下CRT\SRC\DBGDEL.cpp

2. 针对类Class,两种方式体现出具体差异 
   当你通过下列方式分配一个类对象数组:
   class A
   {
   private:
      char *m_cBuffer;
      int m_nLen;
   public:
      A(){ m_cBuffer = new char[m_nLen]; }
      ~A() { delete [] m_cBuffer; }
   };
   A *a = new A[10];
   delete a;         //仅释放了a指针指向的全部内存空间,但是只调用了a[0]对象的析构函数 ,剩下的从a[1]到a[9]这9个用户自行分配的m_cBuffer对应内存空间将不能释放, 从而造成内存泄漏

   delete [] a;      //释放了a指针指向的全部内存空间 并且调用使用类对象的析构函数释放用户自己分配内存空间
   
   在   vc   中对于简单数据类型int,char等的数组使用delete还是delete[]是完全一样的,不过对于类的实例的数组来说就必须使用delete[],否则可能会引起该类的析沟函数不会被正确调用。

 

总结:在不明确指针指向的是否是数组还是单个变量时,用delete[] p;来删除指针是最好的办法,不会引起上面说的间接内存泄露。

 

指针就只是一个表示地址的变量,它的应用重点在于它指向了什么,在初始化赋值后,如果再次给指针变量赋值(不是给指针指向的内容赋值)的时候一定要注意对后续工作的影响。

posted on 2014-03-16 15:34  起床吹台风睡觉开电脑  阅读(308)  评论(0编辑  收藏  举报

导航