概念
指針用于指向?qū)ο笠榷。唧w來說指針保存的是另一個對象的地址
string s = "Hello world";
string *sp = &s;
sp為一個指向string
類型的指針傍妒,上面語句初始化sp指向string
類型對象s森逮。
指針的定義和初始化
每個指針都有一個與之關(guān)聯(lián)的數(shù)據(jù)類型,該數(shù)據(jù)類型決定了指針?biāo)赶虻膶ο蟮念愋湍肌++中使用符號把一個標(biāo)識符聲明為指針如下:
vector<int> *pvec;
int *ip1,*ip2;
string *pstring;
double *dp;
** 理解指針聲明語句時,從右向左閱讀 **
string *pstr;
把pstr定義為一個指向string
類型對象的指針變量。
在聲明語句中请梢,符號可用在指定類型對象列表的任何位置:
double dp,*dp2;
該語句定義了一個double
類型的dp對象,及一個指向double
類型對象的指針dp2;
另一種聲明指針的風(fēng)格
定義指針變量時可用空格將符號與其后的標(biāo)識符分割開來力穗。如下:
string* ps;
//該語句把ps定義為一個指向string
類型對象的指針毅弧。
需要注意的是如下語句:
string* ps1,ps2;
該語句實際上只把ps1定義為指針,ps2不是指針当窗,只是一個string對象够坐。如果需要在一個聲明語句中定義兩個指針必須在每個變量標(biāo)識符前加符號聲明:
string* ps1,*ps2;
指針可能的取值:
一個有效指針必定是以下三種狀態(tài)之一:保存一個特定對象的地址;指向某個對象后面的另一個對象崖面;或為0值元咙。保存0值表明指針不指向任何對象。未初始化的指針是無效的巫员,知道給該指針賦值后才可使用它庶香。如下:
int ival = 1024;//
int *pi = 0;//pi初始化為0不知道任何對象。
int *pi2 = &ival;//pi2初始化oval的地址
int *p3;//未初始化
pi = pi2;//pi,pi2指向相同的對象
pi2 = 0;//pi2為0不指向任何對象简识。
指針初始化和賦值操作的約束
對指針進行初始化或賦值只能使用以下四種類型的值:
- 0值常量表達式
- 類型匹配的對象的地址
- 另一個對象之后的下一地址
- 同類型的另一個有效指針
直接把int型變量賦給指針是非法的赶掖,但允許把數(shù)值0或在編譯時可獲得0值得const量賦給指針:
int ival;
int zero = 0;
const int c_ival = 0;
int *pi = ival;//錯誤感猛,
pi = zero;//錯誤
pi = c_ival;//正確
pi = 0;//正確,直接初始化為0
另外
int *pi = NULL奢赂;
也是正確的陪白,NULL為C++從C語言繼承下來的預(yù)處理變量,在編譯時會自動被數(shù)值0替換呈驶。
void*指針
C++提供了一種特殊的指針類型void*拷泽,它可以保存任何類型對象的地址:
double obj = 3.14;
double *pd = &obj;
void *pv = &obj;
pv = pd;
void*
指針表面該指針與一地址值相關(guān),但不清楚存儲在此地址上的對象的類型袖瞻。
void*
指針只支持幾種有限的操作:與另一個指針進行比較司致;向函數(shù)傳遞void*
指針或從函數(shù)返回void*
指針,給另一個void*
指針賦值聋迎。不允許使用void*
指針操縱它所指向的對象脂矫。
指針操作
指針提供間接操縱其所指對象的功能。對指針進行解引用可訪問它所指向的對象霉晕,"*"操作符將獲取指針?biāo)傅倪@個對象:
string s("hello world");
string *sp = &s;
cout<<*sp;輸出位hello world庭再;對sp進行解引用操作將獲得s的值。
給指針賦值與通過指針進行賦值這兩種操作的區(qū)別
給指針賦值牺堰,沒有使用解引用操作拄轻,修改的是指針本身的值。
通過指針進行賦值伟葫,對左操作數(shù)進行解引用恨搓,修改的是指針?biāo)笇ο蟮闹怠?/p>
string s1("some value");
string *sp1 = &s1;
string s2("another");
string *sp2 = &s2;
sp1=sp2;//給指針賦值,此時sp1指向了s2.
*sp1 = "a new value";//通過指針近賦值筏养,將sp1所指對象的值修改了斧抱。
指針和引用的比較
二者都可間接訪問另一個值,但二者的區(qū)別在于引用總是指向某個對象定義引用時沒有初始化是錯誤的渐溶;還有就是給引用賦值修改的是該引用所關(guān)聯(lián)的對象的值辉浦,并不是使用引用于另一個對象關(guān)聯(lián),引用已經(jīng)初始化就始終指向同一個特定對象(這也是引用必須在定義時初始化的原因)茎辐。
int ival = 1024,ival2 = 2048;
int *p1 = &ival,*p2 = &ival2;
p1 = p2;//p1現(xiàn)在指向ival2
關(guān)于引用操作:
int &ref = ival,&ref2 = ival2;
ref = ref2;//ival現(xiàn)在值為2048
指向指針的指針
指針本身也是可用指針指向的內(nèi)存對象宪郊。指針占用內(nèi)存空間存放其值,因此指針的存儲地址可存放在指針中拖陆。C++中使用**操作符指派一個指針指向另一個指針弛槐。
int ival = 1024;
int *pi = &ival;//pi存放ival的地址
int **ppi = π//ppi存放的是pi的地址,*ppi去的是pi的值也就是ival的地址慕蔚,**ppi取的是ival的值1024.
對ppi進行解引用獲得ppi所指向的對象丐黄,指向int類型的變量的指針pi.
int *pi2 = *ppi;//pi2指向了pi.
指針和const限定符
指向const對象的指針
const double *ptr;
這里ptr
是一個指向double類型const對象
的指針斋配,const
限定了ptr指針
所指向的對象類型孔飒;ptr
本身并不是const
的灌闺,允許給ptr
重新賦值使其指向另一個const
對象。但不能通過ptr
修改其所指對象的值坏瞄。如:
*ptr = 42;//錯誤
另外把一個const對象的地址賦值給一個普通的桂对,非const對象的指針也會導(dǎo)致編譯錯誤:
const double pi = 3.14;
double *ptr1 = π///錯誤
const double *ptr3 = π//正確
但是允許把非const對象的地址賦值給指向const對象的指針:
double deal = 3.14;
ptr = &dval;//正確
盡管dval不是const對象,但任何企圖通過ptr修改其值的行為都會導(dǎo)致編譯時錯誤鸠匀。ptr一經(jīng)定義就不允許修改其所指對象的值蕉斜。如該指針指向非const對象,同樣遵守該規(guī)則缀棍。
還有需要注意的是不能使用void指針保存const對象的地址宅此,必須使用const void類型的指針保存const對象的地址。
const int verse = 42;
const void *cpv = &iverse;//正確
void *pv = &iverse;//錯誤
const指針
int numb = 0;
int *const cur = &numb;
上述定義語句為cur是指向int型對象的const指針爬范,const指針的值不能修改父腕,意味著不能使cur指向其他對象;const指針也必須在定義時初始化青瀑。
指向const對象的const指針
const double pi = 3.14;
const double *const ptr = & pi;
上面代碼中璧亮,既不能修改ptr所指向?qū)ο蟮闹担膊荒苄薷脑撝羔樀闹赶虺饽选5诙衐iamante從右向左閱讀:ptr指向一個const指針枝嘶,指向double類型的const對象。
const限定符既可以放在類型前也可以放在類型后如:
string const s1;
const string s2;//二者等價哑诊。