避免野指針的產生
“野指針”的成因主要有:
1)指針變量沒有被初始化。任何指針變量剛被創建時不會自動成為NULL指針,它的缺省值是隨機的,它會亂指一氣。所以,指針變量在創建的同時應當被初始化,要么將指針設置為NULL,要么讓它指向合法的內存。
char *p; //此時p為野指針
2)指針p被free或者delete之后,沒有置為NULL,讓人誤以為p是個合法的指針.
char *p=new char[10]; //指向堆中分配的內存首地址,p存儲在棧區 cin>> p; delete []p; //p重新變為野指針
3)指針操作超越了變量的作用范圍。
char *p=new char[10]; //指向堆中分配的內存首地址 cin>> p; cout<<*(p+10); //可能輸出未知數據
指針的注意點:
a.指針指向常量存儲區對象
char *p="abc";
此時p指向的是一個字符串常量,不能對*p的內容進行寫操作,如srtcpy(p,s)是錯誤的,因為p的內容為“abc”字符串常量,該數據存儲在常量存儲區,但可以對指針p進行操作,讓其指向其他的內存空間。
b.資源泄漏
問題:
1 #include<iostream> 2 using namespace std; 3 void main() 4 { 5 char *p=new char[3]; //分配三個字符空間,p指向該內存空間 6 p="ab"; //此時p指向常量“ab”,而不再是new char分配的內存空間了,從而造成了資源泄漏 7 delete []p; //釋放時報錯 8 }
結果:卡死

改進:
1 #include<iostream> 2 using namespace std; 3 void main() 4 { 5 char *p=new char[3]; //分配三個字符空間,p指向該內存空間 6 strcpy(p,"ab"); //將"ab"存儲到p指向的內存空間 7 delete []p; //ok 8 }
結果:正確
c.內存越界
1 char *p=new char[3]; //分配三個字符空間,p指向該內存空間 2 strcpy(p,"abcd"); //將abcd存處在分配的內存空間中,由於strlen("abcd")=4>3,越界 3 delete []p; //ok
d.返回值是指針
問題:數組p[]中的內容為“hello world”,存儲在棧區,函數結束時內容被清除,p變為野指針,可能導致亂碼
1 #include<iostream> 2 using namespace std; 3 char *f() 4 { 5 char p[]="abc"; 6 return p; 7 } 8 void main() 9 { 10 cout<<f()<<endl; 11 }
結果:
改進:
1.加static限定,延長數組生存期
1 #include<iostream> 2 using namespace std; 3 char *f() 4 { 5 static char p[]="abc"; //此時數組為靜態數組,存儲在全局/靜態區,生存期到程序結束,因此函數結束時不會銷毀p 6 return p; 7 } 8 void main() 9 { 10 cout<<f()<<endl; 11 }
結果:
2.定義成指針型數組
1 #include<iostream> 2 using namespace std; 3 char *f() 4 { 5 char *p="abc"; //"abc"存儲在文字常量區,p是指向常量的指針,生存期到程序結束 6 return p; 7 } 8 void main() 9 { 10 cout<<f()<<endl; 11 }
結果:
3.動態分配存儲空間,存儲在堆區
1 #include<iostream> 2 using namespace std; 3 char *f() 4 { 5 char *p=new char[5]; //動態分配存儲空間,p指向堆區 6 strcpy(p,"abc"); // 這里不能用p="abc",前面已經說明 7 return p; 8 } 9 void main() 10 { 11 cout<<f()<<endl; 12 }
結果:
e.指針做形參
即所謂的地址傳遞,我們都知道地址傳遞的方式,形參的改變會導致實參的改變,但要注意的是,這里的改變是指指針所指內容的改變,而不是指針值的改變。因此,當形參改變會導致實參改變時,指針所指的內容是非const類型的,否則會出錯。
1.改變指針內容:
1 void swap(int *a,int *b) //交換的是*a,*b,即指針的內容,而不是指針a,b 2 { 3 int t; 4 t=*a; 5 *a=*b; 6 *b=t; 7 }
2.改變指針值:
1 #include<iostream> 2 using namespace std; 3 void fun(char *p) 4 { 5 p="cba"; //“cba”存放在文字常量區,讓p指向常量"abc",這里改變的是指針值,實參並不會改變 6 } 7 void main() 8 { 9 char *p="abc"; //“abc”存放在文字常量區,p指向常量"abc" 10 fun(p); 11 cout<<p<<endl; //輸出"abc",而不是"bca" 12 }
結果:
繼續看下面的情況,修改指針的內容:
1 #include<iostream> 2 using namespace std; 3 void fun(char *p) 4 { 5 p[0]='c'; //改變p的內容,即修改p[0] 6 } 7 void main() 8 { 9 char *p="abc"; //p指向常量"abc" 10 fun(p); 11 cout<<p<<endl; //error,p所指內容為常量,不能修改 12 }
結果:
注:p="ab"和strcpy(p,"ab"),含義不一樣,前者指針p指向常量“ab”存儲區域的首地址,改變了p最開始指向的new申請的內存空間;而后者是將“ab”分配到new申請的內存空間中;