從監視窗口中,我們可以看見雖然程序的第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)
我們來看一下在stdio.h中關於關鍵字NULL的定義:
1
2
3
#ifndef NULL
4
#ifdef __cplusplus
5
#define NULL 0
6
#else
7
#define NULL ((void *)0)
8
#endif
9
#endif
注意上面定義的第5行。這裡其實就說明了NULL就是0。也就是說,我們在刪除完指針p之後,一定要把它變成空指針!只有這樣,才會杜絕上面程序中出現的野指針的錯誤。
p.s. 對於NULL的應用,我們不應該僅限於上面的方法,還可以應用NULL來判斷指針是否初始化成功了,如下例if中的判斷方法:
01
#include
02
using namespace std;
03
04
int main()
05
{
06
int *p=new int;
07
if (p==NULL)
08
{
09
//判斷指針p是不是空指針,如果是空指針,那麼程序在這裡就應該報錯
10
//報錯的方法有很多,比如說返回一個ERROR值:
11
//return ERROR;
12
}
13
14
//判斷了操作成功之後我們才能進行一系列的操作
15
//...
16
17
//用完指針p之後,一定要將其刪掉。這樣可以杜絕野指針的存在
18
delete p;
19
//刪除指針p之後,一定要加上下面這句話,免得成為野指針
20
p=NULL;
21
}