野指針及c++指針使用注意點


避免野指針的產生

“野指針”的成因主要有:

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申請的內存空間中;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM