void*爲「無類型指針」,能夠指向任何類型的數據,可是訪問數據時必須指明。函數
看下面的小例子:spa
int a = 5; void *p = &a; cout<<*p; //編譯錯誤,'void*' is not a pointer-to-object type cout<<*(int*)p; //ok cout<<*(double*)p; //能夠經過編譯和運行,可是結果確定是錯誤的
其實,void* 指針能作的事情頗有限:1.指針比較。2.做爲函數傳入參數,或返回參數。3.賦給另外一個void* 指針。
指針
不能經過void* 指針來訪問它所指的對象(由於咱們不知道對象的類型,而對象類型決定了能夠進行哪些操做。),若是想訪問它所指的類型,須要顯式指出。code
int i = 42; int *p = &i; //指針p指向i int *&r = p; //r是指針p的引用,r是一個指向int類型的指針的引用 *r = 50; //here, i==50, *p == 50
int i = 42; const int &r1 = i; //ok r1 = 100; //error, cause it's const i = 100; cout << r1; //here, r1==100
const引用能夠用普通對象來初始化,可是不能經過cont引用來修改該對象。看下面的小例子:對象
double dval = 3.14; const int &r1 = dval; dval = 3.15; cout<<r1; //ri == 3
這裏,能夠用const引用綁定不是該類型的對象(int r1 = dval;就不能夠)。其實這裏引用綁定的是一個臨時對象。至關於:ip
const int temp = dval; //建立了一個臨時對象,爲3 const int &r1 = temp; //將引用與臨時對象綁定,因此結果輸出爲3
指針不可能知道它所指向的對象是const對象仍是普通對象,因此它對它所指向的全部對象都當成是const對象。指向const對象的指針能夠被認爲是「它們認爲它們本身指向const對象的指針」。it
不能經過該指針修改對象的值,不過能夠改變該指針指向的對象。pip
const double pi = 3.14; double *ptr = π //error,不能用普通指針存儲const對象地址 const double *cptr = π //ok *cptr = 42; //error,不能經過const指針賦值 double dval = 3.14; cptr = &dval; //ok:可是不能經過cptr來改變dval的值
//能夠改變該指針的指向對象 const int v1 = 3; const int v2 = 4; const int *p = &v1; cout<<*p<<endl; //output 3 p = &v2; //改變指向的對象 cout<<*p<<endl; //output 4
任何給const指針從新指向新對象的作法都是錯誤的。不過,能夠經過const指針修改對象的值。編譯
int errNumb = 0; int *const curErr = &errNumb; //curErr will always point to errNumb const double pi = 3.14159; const double *const pip = π //pip is a const pointer to a const object
最簡單的理解方式是從右往左讀,curErr is a constant pointer to an object of type int.class
//能夠改變該指針指向對象的值 int v3 = 5; int v4 = 10; int *const p2 = &v3; *p2 = 6; //ok,改變該對象的值 p2 = &v4; //error,由於是const指針,不能從新指向新對象 cout<<*p2<<endl; //output 6
總結:指向const對象的指針 和 const指針 是不一樣的。前者認爲本身指向的對象是const,因此不能經過該指針修改對象的值;後者認爲本身是const指針,不能從新指向新對象。前者能夠指向新對象,後者能夠更改對象的值。通常來講,前者用的更普遍,經常使用於函數的傳入參數,來保證在函數體中不改變對象的值。