new和delete
我们在编程时一般要new和delete配合使用,否则会引起内存泄露,请看下面这个程序:
-
#include <iostream>
-
#include <windows.h>
-
using namespace std ;
-
-
void fun1 ( int * &p )
-
{
-
int i = 10 ;
-
p = &i ;
-
cout <<i << " " << &i <<endl ;
-
}
-
-
int main ( )
-
{
-
int *p = new int ( ) ;
-
cout << *p << " " <<p <<endl ;
-
fun1 (p ) ;
-
cout << *p << " " <<p <<endl ;
-
Sleep ( 1000 ) ;
-
cout << *p << " " <<p <<endl ;
-
//delete p;
-
return 0 ;
-
}
运行结果如下:
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加上以后,程序在运行到最后,会出现一个警告。
想来想去,其实此时已经完全没有必要delete了,因为系统释放i的时候相当于已经执行了delete p的操作,因为i的内容被释放,而p又指向i,当然p也同时被释放。
这时候又有疑问了,既然p已经在func1之后完毕后被释放了,那最后为什么还能输出p和*p呢?
因为delete p的操作,其实就是将*p的内容销毁,p的值依然保持不变,所以依然可以在delete p以后使用p。
不信的话可以将上述程序稍微修改一下:
-
#include <iostream>
-
#include <windows.h>
-
using namespace std ;
-
-
void fun1 ( int * &p )
-
{
-
int i = 10 ;
-
p = &i ;
-
cout <<i << " " << &i <<endl ;
-
}
-
-
int main ( )
-
{
-
int *p = new int ( ) ;
-
cout << *p << " " <<p <<endl ;
-
//fun1(p);
-
cout << *p << " " <<p <<endl ;
-
Sleep ( 1000 ) ;
-
delete p ;
-
cout << *p << " " <<p <<endl ;
-
return 0 ;
-
}
运行结果如下:
0 003B33A0
0 003B33A0
-572662307 003B33A0
可见,在delete p执行以后,p的值并没有发生变化,只是p所指向的内容被销毁,变为不可知状态。
最后,总结一下,new操作一定要配合一个delete操作,但delete不一定是显式的调用,可以由系统帮助完成。而delete p其实只是销毁内容,即*p,而p本身的值却并没有发生变化。