C++ Primer 學習筆記與思考_8 指標和const的那些麻煩
阿新 • • 發佈:2019-02-18
(一)陣列的下標和指標的關係
我們以前知道,在表示式中使用陣列名時,實際使用的是指向陣列第一個元素的指標。當我們使用下標訪問陣列時,實際上是對指向陣列元素的指標做下標操作,只要陣列指向陣列元素,就可以對它進行下標操作。
1.指向const物件的指標
①如果我們定義的指標是指向const物件的,那麼這個指標也必須具有const特性。
但是const限定的是指標所指向的物件型別,而不是指標本身,也就是說指標並不是const, 定義時不用進行初始化,並且可以對指標重新賦值,僅僅是不能改變指標指向的物件而已。
②還有我們也允許將非const物件的地址賦給指向const物件的指標,但是此時物件不可通過const指標修改了,即便物件本身並不是const,但是卻可以通過其他非const指標修改。
這個就比較好理解了,const指標說明指標本身的指向是不可以改變的,也就是不能改變定義時指向的物件。
如果我們要求指標的指向不允許改變並且指標指向的物件的值也不能夠改變,那麼我們就要這樣宣告:ptr首先是一個const指標,指向const物件.
我們使用typedef隱藏指標時,要特別注意不要把typedef簡單的當作文字擴充套件,尤其和const一起出現的時候。
注意一下三種定義方式都是等價的:
我們以前知道,在表示式中使用陣列名時,實際使用的是指向陣列第一個元素的指標。當我們使用下標訪問陣列時,實際上是對指向陣列元素的指標做下標操作,只要陣列指向陣列元素,就可以對它進行下標操作。
像下面程式中的p[-1]這種表示方法,可能乍一看比較彆扭,但是就像我們平常用的,陣列名就可以看作是指向首元素地址的指標,後面[]內的只是偏移量,這樣理解的話,哪怕是負值我們也很好理解了。
(二)指標和const限定符#include <iostream> #include <string> #include <cstring> using namespace std; int main() { char s[]={'a','b','c'}; char *p=&s[1]; char c=p[-1],d=p[1]; cout<<"p[-1]: "<<c<<endl; cout<<"p[0]: "<<p[0]<<endl; cout<<"p[1]: "<<d<<endl; return 0; }
1.指向const物件的指標
①如果我們定義的指標是指向const物件的,那麼這個指標也必須具有const特性。
但是const限定的是指標所指向的物件型別,而不是指標本身,也就是說指標並不是const, 定義時不用進行初始化,並且可以對指標重新賦值,僅僅是不能改變指標指向的物件而已。
②還有我們也允許將非const物件的地址賦給指向const物件的指標,但是此時物件不可通過const指標修改了,即便物件本身並不是const,但是卻可以通過其他非const指標修改。
2. const指標#include <iostream> #include <string> #include <cstring> using namespace std; int main() { char s[]={'a','b','c'}; char *p=&s[1]; char c=p[-1],d=p[1]; cout<<"p[-1]: "<<c<<endl; cout<<"p[0]: "<<p[0]<<endl; cout<<"p[1]: "<<d<<endl; return 0; }
這個就比較好理解了,const指標說明指標本身的指向是不可以改變的,也就是不能改變定義時指向的物件。
double pi=3.44;
double* const p=π;
double a=4.5;
p=&a; //error
3.指向const物件的const指標如果我們要求指標的指向不允許改變並且指標指向的物件的值也不能夠改變,那麼我們就要這樣宣告:ptr首先是一個const指標,指向const物件.
const double pi=3.14;
const double *const ptr=π
4.指標和typedef我們使用typedef隱藏指標時,要特別注意不要把typedef簡單的當作文字擴充套件,尤其和const一起出現的時候。
估計我們大部分人都會將其錯誤的認為是指向const物件的指標,因為我們僅僅文字擴充套件的話和前面的形式一樣。但是恰恰不能簡單的這樣理解,const修飾的是pstring型別,pstring是指標型別。所以cstr應該是指向string型別的const指標。string s; typedef string* pstring; const pstring cstr;
注意一下三種定義方式都是等價的:
string s;
typedef string* pstring;
const pstring cstr=&s;
pstring const cstr2=&s;
string *const cstr3=&s;