指針是C語言中的難點,C++中自然也免不了其身影。
以下是我學習中的積累,不足之處望不吝賜教。
指針
Const int* pstr 不能修改被指向的對象,可以使指針指向其他對象
如:const int* pvalue {&value};
*pvalue=6; //will not compile
pvalue=nullptr; //ok
Int* const pstr 不能修改指針中存儲的地址,可修改指向的對象
如:Int* const pvalue {&value};
*pvalue=6; //ok
pvalue=nullptr; //will not compile
Const int* const Pstr 指針和指向的對象都不能修改
如:Const int* const pvalue {&value};
*pvalue=6; //will not compile
pvalue=nullptr; //will not compile
指針數組 char* pstr[]
數組指針 char (*pstr)[4]
double beans[3][4];
double* pbeans;
pbeans=&beans[0][0]; //指向數組第一個元素的位置
pbeans=&beads[0]; //指向數組第一行元素的位置
double(*pbeans)[4] = beans; //非=&beans,列數要相等
函數指針
double (*pfun) (char*,int)
指針參數:
先看一段雙指針(二級指針)在mian函數裡的地址輸出
1 int main() 2 { 3 int v = 9; 4 int *p1 = &v; 5 int **p2 = &p1; 6 7 cout << "v= " << dec << v << endl; 8 cout << "&v= " << hex << &v << endl; 9 cout << "p1= " << hex << p1 << endl; 10 cout << "&p1= " << hex << &p1 << endl; 11 cout << "&*p1=" << hex << &(*p1) << endl; 12 13 cout << "p2= " << hex << p2 << endl; 14 cout << "&p2= " << hex << &p2 << endl; 15 cout << "&(*p2)=" << hex << &(*p2) << endl; 16 17 cin.get(); 18 return 0; 19 }
注:從中不難看出指針間的關系,二級指針p2指向p1,物理內存p2所在位置存儲了指針p1的地址,而p1所在物理內存所在位置存儲了變量V的地址。
當指針同C語言中那樣作為參數傳遞時,可以通過地址來觀察函數調用情況。
1 void SetPoint(int *pu) 2 { 3 cout << "pu= " << hex << pu << endl; 4 cout << "&pu= " << hex << &pu << endl; 5 *pu=*pu + 1; 6 } 7 int main() 8 { 9 int a = 5; 10 int *pt = &a; 11 SetPoint(&a); 12 13 cout << "&a= " << hex << &a << endl; 14 cout << "pt= " << hex << pt << endl; 15 cout << "&pt= " << hex << &pt<<endl; 16 cout << "&*pt=" << hex << &(*pt)<<endl; 17 cout << "a= " << dec << a<< endl; 18 19 cin.get(); 20 return 0; 21 }
注:由上代碼可以看出參數’pu‘的地址不等於變量’a‘的地址,所以‘pu'只是作為中間臨時變量指向了變量’a'。
而'a'的值卻被改變,則說明編譯器創建了臨時變量對‘a'進行了操作。
1 void SetPoint(int &pu) 2 { 3 cout << "pu= " << hex << pu << endl; 4 cout << "&pu= " << hex << &pu << endl; 5 pu=pu + 1; 6 } 7 int main() 8 { 9 int a = 5; 10 int *pt = &a; 11 SetPoint(a); 12 13 cout << "&a= " << hex << &a << endl; 14 cout << "&pt= " << hex << &pt<<endl; 15 cout << "&*pt=" << hex << &(*pt)<<endl; 16 cout << "a= " << dec << a<< endl; 17 18 cin.get(); 19 return 0; 20 }
注:而c++中的引用則是直接對變量’a'進行操作,由上面輸出可以看出,‘pu’的地址等於‘a'的地址。
雙指針:
網上常出現的一道面試題如下
void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(char) * num); } int main() { char *str = nullptr; GetMemory(str, 100); strcpy(str, "Hello"); cout << str << endl; return 0; }
我試著輸出了str和p的地址,結果於上。可以看出兩個變量的地址並不一樣,因此 p 是作為函數運行中的臨時變量。可知此處與直接傳參數一樣,只會被當做臨時變量處理。
可以將函數中的臨時變量作為返回值傳給 str ,以達到想要的效果。
char * GetMemory(char *p, int num) { p = (char *)malloc(sizeof(char) * num); return p; } int main() { char *str = nullptr; str=GetMemory(str, 100); strcpy(str, "Hello"); cout << str << endl; return 0; }
效率高的還是直接用雙指針(二級指針)
void GetMemory(char **p, int num) { *p = (char *)malloc(sizeof(char) * num); } int main() { char *str = nullptr; GetMemory(&str, 100); strcpy_s(str,6, "Hello"); cout << str << endl; cin.get(); return 0; }
思考輸出的地址, 指針 p [00AFFDDC] 指向了 str [00AFFEB4]的地址。從而以二級指針作為橋梁曲線操作來達到直接為 str 分配空間的目的。
由此,進一步,以後申請動態分配內存,可以考慮使用雙指針。在大的數據面前,復制移動顯然浪費時間,也可以考慮使用。