C++中關(guān)于指針與引用

摘抄自————《C++ Primer中文第五版》

1.引用(reference):為對象起了另外一個(gè)名字,引用類型引用(refers to)另外一種類型。通過將聲明符寫成 &d (&:取地址操作符)的形式來定義引用類型,其中d是聲明的變量名:

int ival = 1024;
int &referVal = ival;   //refVal指向ival(是ival的另一個(gè)名字) 
int &refaVal2;   //錯(cuò)誤:引用必須被初始化

注意:
??a. 引用必須被初始化,程序把引用和它的初始值對象一直綁定在一起。因?yàn)闊o法令引用重新綁 ???定到另外一個(gè)對象,因此引用必須初始化。
??b. 引用并沒有實(shí)際地址,只是為一個(gè)已存在的對象所起的另外一個(gè)名字。
??c. 對引用的所有操作都是在與之綁定的對象上進(jìn)行的。
??d. 引用的類型與綁定的對象類型必須一致。

2. 指針(pointer):是指 “ 指向(point to) ” 另外一種類型的復(fù)合類型。與引用類似,指針也實(shí)現(xiàn)了對其他對象的間接訪問。定義指針類型的方法將聲明符寫成 *d 的形式,其中 d 是變量名。

int i = 10;
int *ipl = &i;   //ipl是指向int型對象的指針
int *pr, *pi;     //定義兩個(gè)int型指針

2.1 指針與引用的不同點(diǎn):

??其一,指針本身就是一個(gè)對象,允許對指針賦值和拷貝,而且在指針的生命周期內(nèi)它可以先后指向幾個(gè)不同的對象。

??其二,指針無須再定義時(shí)賦初值。和其他內(nèi)置類型一樣,在塊作用域內(nèi)定義的指針如果沒有被初始化,也將擁有一個(gè)不確定的值。

2.2 指針值:

a. 指向一個(gè)對象。
b. 指向緊鄰對象對象所占空間的下一個(gè)位置。
c. 空指針,意味著指針沒有指向任何對象。
d. 無效指針,也就是上述情況之外的其他值。

2.3 某些符號有多重含義

int i = 42;
int &r = i;  // &緊隨類型名出現(xiàn),因此是聲明的一部分,r是一個(gè)引用
int *p;  // *緊隨類型名出現(xiàn),因此是聲明的一部分,p是一個(gè)指針
p = &i;  // &出現(xiàn)在表達(dá)式中,是一個(gè)取地址符
*p = i;  // *出現(xiàn)在表達(dá)式中,是一個(gè)解引用符
int &r2 = *p;  // &是聲明的一部分, *是一個(gè)解引用符

2.4 空指針

??空指針(null pointer)不指向任何對象,在試圖使用一個(gè)指針之前代碼可以首先檢查是否為空。以下是幾個(gè)生成空指針的方法:

int *p1 = nullptr;  //C++11新標(biāo)準(zhǔn)方法。等價(jià)于 int *p1 = 0;
int *p2 = 0;  //直接將p2初始化為字面常量0
//需要首先 #include cstdlib
int *p3 = NULL;  // 等價(jià)于 int *p3 = 0;

2.5 void* 指針

??void *指針是一種特殊的指針類型,可用于存放任意對象的地址。一個(gè)void * 指針存放著一個(gè)地址,這一點(diǎn)和其他指針類似。不同的是。我們對該地址中到底是個(gè)什么類型的對象并不了解:

double obj = 3.14, *pd = &obj;
// 正確:void* 能存放任意類型對象的地址
void *pv = &obj;  // obj可以是任意類型的對象
pv = pd;   // pv可以存放任意類型的指針

2.6 指向指針的指針

int ival = 1024;
int *pi = &ival;  // pi 指向一個(gè)int型的數(shù)
int **ppi = π  // ppi 指向一個(gè)int型的指針

??這里pi是指向int型數(shù)的指針,而ppi是指向int型指針的指針,如圖:


指向指針的指針.png

??解引用 int 型指針會得到一個(gè)int型的數(shù),同樣,解引用指向指針的指針會得到一個(gè)指針。此時(shí)為了訪問最原始的那個(gè)對象,需要對指針的指針做兩次解引用:

cout  << "The value of ival\n"
      << "direct value: " << ival << "\n"
      << "indirect value: " << *pi << "\n"
      << "double indirect value: " << **ppi
      << endl;

??該程序使用三種不同的方式輸出了變量 ival 的值: 第一種直接輸出;第二種通過int型指針pi輸出;第三種兩次解引用ppi,取得ival的值。

2.7 指向指針的引用
??引用本身不是一個(gè)對象,因此不能定義指向引用的指針。但指針是對象,所以存在對指針的引用:

int t = 42;
int *p;  // p 是一個(gè)int型指針
int *&r = p;  // r是一個(gè)對指針p的引用

r = &i;  // r引用了一個(gè)指針,因此給r賦值&i就是令p指向i
*r = 0;  // 解引用 r 得到 i,也就是 p 指向的對象,將 i 的值改為0

??要理解 r 的類型到底是什么,最簡單的辦法是從右往左閱讀 r 的定義。離變量名最近的符號(此例中是 &r 的符號是 &)對變量的類型有最直接的影響,因此 r 是一個(gè)引用。聲明符的其余部分用以確定 r 引用的類型是什么,此例中的符號 * 說明 r 引用的是一個(gè)指針。最后,聲明的基本數(shù)據(jù)類型部分指出 r 引用的是一個(gè) int 指針。

因此這里 int *&r = p;
應(yīng)該看成是 對 int*(int型的指針)的引用,所以對 p指針的操作和對 r 引用的操作是一樣的。

2.8 另外: 關(guān)于& 和 *& 理解

int i = 100;
int *p = &i;
int &pr = *p;  // *是一個(gè)解引用符,由*得到指針p所指的對象
int *&pi = p;

這里 &pr 和 *&pi 表面上看值都是一樣的,但是有一點(diǎn)不同

pr 是指針p所指對象的引用
pi 是指針p的引用

??假如p指針指向的是一個(gè)數(shù)組,那么 pr只能訪問p的首元素(單一對象),而pi則可以訪問p的整個(gè)數(shù)組(數(shù)組的地址)。

2.9 const 指針
??指針是對象而引用不是,所以指針本身可以定為常量。常量指針(const pointer)必須初始化,一旦初始化完成,則它的值(也就是存放在指針中的那個(gè)地址)就不能再改變了。把 * 放在 const 關(guān)鍵字之前用以說明指針是一個(gè)常量,這樣的書寫形式隱含著一層意味,即不變的是指針本身的值而非指向的那個(gè)值:

int errNumb = 0;
int *const curErr = &errNumb;  // curErr 將一直指向 errNumb
const double pi =3.14159;  
const double *const pip = &pi;  //pip是一個(gè)指向常量對象的常量指針

??要想弄清楚上述聲明的含義,最有效的辦法是從右向左閱讀。離 currErr 最近的符號是 const,意味著 currErr 本身是一個(gè)常量對象,對象的類型由聲明符的其余部分確定。聲明符中的下一個(gè)符號是*,意思是 currErr 是一個(gè)常量指針。最后,該聲明語句的基本數(shù)據(jù)類型部分確定了常量指針指向的是一個(gè) int 對象。與之相似,我們也能推斷出,pip是一個(gè)常量指針,它指向的對象是一個(gè)雙精度浮點(diǎn)型常量。
??指針本身是一個(gè)常量并不意味著不能通過指針修改其所指對象的值,能否這樣做完全依賴于所指對象的類型。例如,pip 是一個(gè)指向常量的常量指針,則不論是 pip所指的對象值還是pip自己存儲的那個(gè)地址都不能改變。相反的,curErr 指向的是一個(gè)一般的非常量整數(shù),那么就完全可以用 curErr 去修改 errNumb 的值:

*pip = 2.72;  // 錯(cuò)誤:pip是一個(gè)指向常量的指針
// 如果 curErr 所指的對象(也就是errNumb)的值不為 0 
if (*curErr) 
{
  errorHandler();
  *curErr = 0;  //正確:把curErr所指的對象的值重置
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容