new 一定要与 delete 配合使用吗?

时间:2021-01-04 05:18:38

new和delete

我们在编程时一般要new和delete配合使用,否则会引起内存泄露,请看下面这个程序:

  1. #include <iostream>
  2. #include <windows.h>
  3. using  namespace std ;
  4.  
  5. void fun1 ( int  * &p )
  6. {
  7.      int i  =  10 ;
  8.     p  =  &i ;
  9.      cout <<i << " " << &i <<endl ;
  10. }
  11.  
  12. int main ( )
  13. {
  14.      int  *=  new  int ( ) ;
  15.      cout << *p << " " <<p <<endl ;
  16.     fun1 (p ) ;
  17.      cout << *p << " " <<p <<endl ;
  18.     Sleep ( 1000 ) ;
  19.      cout << *p << " " <<p <<endl ;
  20.      //delete p;
  21.      return  0 ;
  22. }

运行结果如下:

0               003B33A0

10            0012FE6C

10            0012FE6C

1000        0012FE6C

        

首先分析一下上面程序的结果,在new了一个int类型的数据后,返回地址给p。(由于new int后面有一个括号,表示初始化内容为0,所以*p为0,p为003B33A0)

然后调用func1,形参为实参的引用,所以其实就是p。将p指向i以后,即将p的值修改为i的地址,而*p即为i。所以第二行和第三行输出结果一样,到此为止比较容易理解。

最后问题出来了,在sleep(1000)以后,为什么p的值发生修改了呢?

其实原因是在func1中i是局部变量,在func1执行完毕后,i需要释放,那么释放到底是什么意思呢?

其实释放就是将变量i对应的内容销毁,标记为未使用状态,那么以后程序可以继续使用这块内存。既然i的内容已经销毁,那么*p的内容也变为不可知的状态,所以在sleep(1000)以后,系统已经将i释放,此刻p依然指向i,但i的内容已经变为不可知状态,在程序中变为1000。而在刚执行完fun1(p)的时候系统还未来得及释放i,所以依然保持10。

好了,问题又来了,注意我在最后把delete p给注释掉了,肯定有人会以为这样会造成内存泄露,其实当初我也是这么认为的,当把delete p加上以后,程序在运行到最后,会出现一个警告。

 

new 一定要与 delete 配合使用吗?


想来想去,其实此时已经完全没有必要delete了,因为系统释放i的时候相当于已经执行了delete p的操作,因为i的内容被释放,而p又指向i,当然p也同时被释放。

这时候又有疑问了,既然p已经在func1之后完毕后被释放了,那最后为什么还能输出p和*p呢?

因为delete p的操作,其实就是将*p的内容销毁,p的值依然保持不变,所以依然可以在delete p以后使用p。

不信的话可以将上述程序稍微修改一下:

  1. #include <iostream>
  2. #include <windows.h>
  3. using  namespace std ;
  4.  
  5. void fun1 ( int  * &p )
  6. {
  7.      int i  =  10 ;
  8.     p  =  &i ;
  9.      cout <<i << " " << &i <<endl ;
  10. }
  11.  
  12. int main ( )
  13. {
  14.      int  *=  new  int ( ) ;
  15.      cout << *p << " " <<p <<endl ;
  16.      //fun1(p);
  17.      cout << *p << " " <<p <<endl ;
  18.     Sleep ( 1000 ) ;
  19.      delete p ;
  20.      cout << *p << " " <<p <<endl ;
  21.      return  0 ;
  22. }

运行结果如下:

0                         003B33A0

0                         003B33A0

-572662307      003B33A0

 

可见,在delete p执行以后,p的值并没有发生变化,只是p所指向的内容被销毁,变为不可知状态。

最后,总结一下,new操作一定要配合一个delete操作,但delete不一定是显式的调用,可以由系统帮助完成。而delete p其实只是销毁内容,即*p,而p本身的值却并没有发生变化。