引用與指標

2021-08-28 06:35:13 字數 4103 閱讀 8556

引用與指標

1、引用

引用(reference)為物件起了另外乙個名字,引用型別引用(refer to)另外一種型別。通過將宣告符寫出&d的形式來定義引用型別,其中d是宣告的變數名。

一般在初始化變數時,初始值會被拷貝到新建的物件中,然後定義引用時,程式把引用和它的初始值繫結在一起,而不是將初始值拷貝給引用。一旦初始化完成,引用將和它的初始值一直繫結在一起。因為無法令引用重新繫結到另外乙個物件,因此引用必須初始化。

引用即別名。引用並非物件,相反的,它只是為乙個已經存在的物件所起的另外乙個名字。

int val = 1024;

int &refval1 = val;  //refval指向val(是val的另外乙個名字)

int &refval2; //報錯:引用必須初始化

定義乙個引用之後,對其進行的所有操作都是在與之繫結的物件上進行的。為引用賦值,實際上是把值賦給了與引用繫結的物件;獲取引用的值,實際上是獲取了與引用繫結的物件的值;以引用作為初始值,實際上是以與引用繫結的物件作為初始值。

refval1 = 2;  //把2賦給refval1所指向的物件,此處即賦給了val

int ii = refval1;  //ii被初始化為val的值,與ii = val;執行結果相同

int &refval3 = refval1;  //refval3繫結到了那個魚refval1繫結的物件上,即繫結到val上

因為引用本身不是乙個物件,所以不能定義引用的引用。

允許在一條語句中定義多個引用,其中每個引用識別符號都必須以&開頭。

幾乎所有引用的型別都要和與之繫結的物件嚴格匹配。

引用只能繫結在物件上,不能與字面值或某個表示式的計算結果繫結到一起。

int i = 1024, i2 = 2048;   //i和i2都是int

int &r = i, r2 = i2;  //r是乙個引用,與i繫結到一起,r2是乙個int

int i3 = 1024, &r3 = i3;  //i3是int,r3是乙個引用,與i3繫結在一起

int &r3 = i3, &r4 = i2;  //r3和r4都是引用

int &refval4 = 10;  //錯誤:引用型別的初始值必須是乙個物件

double dval =3.14;

int &refval5 = dval;  //錯誤:此處引用型別的初始值必須是int型物件

2、指標

定義:指標(pointer)是指向(point to)另外一種型別的復合型別。定義指標的型別的方法是將宣告符寫成*d的形式,其中d是變數名。如果在一條語句中定義了多個指標變數,每個變數前面都必須有符號。

int *ip1, *ip2;  // ip1和ip2均為指向int型物件的指標

double dp, **dp2;  //dp2為指向double型物件的指標,dp為double型物件

獲取物件的位址

指標存放某個物件的位址,獲取該位址需要使用取位址符(&)

在宣告語句中指標的型別實際上被用於指定它所指向物件的型別,所以除了兩種型別意外,其他所有指標的型別都要和它所指向的物件型別嚴格匹配。

因為引用不是物件,沒有實際的位址,所以不能定義指向引用的指標。

int ival = 42, &ref = ival; 

int *p = &ival;  //p存放變數ival的位址,或者說p是指向變數ival的指標

double dval; 

double *pd = &dval;  //初始值double型別物件的位址

double *pd2 = pd;  //初始值是指向double物件的指標

int *pi = pd;  //錯誤:指標pi的型別和pd的型別是不匹配的

指標的值

指向乙個物件

指向緊鄰物件所佔空間的下乙個位置

空指標,意味著沒有指向任何物件

無效指標,也就是上述情況之外的其他值

試圖拷貝或以其他方式訪問無效指標將引發錯誤,編譯器不負責檢查此類錯誤。

第2和第3種形式的指標雖然有效,但是由於沒有指向任何具體物件,所以試圖訪問此類指標物件的行為也不被允許。

利用指標訪問物件

指標指向乙個物件,則允許使用解引用符(*)來訪問該物件。

對指標解引用會得到所指的物件,因此如果給解引用的結果賦值,實際上也就是給指標所指的物件賦值。

解引用操作僅適用於那些確實指向了某個物件的有效指標。

int ival = 42;  //

int *p = &ival;  //p存放著變數ival的位址,或者說p是指向變數ival的指標

cout << *p;  //由符號*得到指標p所指的物件,輸出42

*p = 0;  //由符號*得到p所指的物件,即可由p為變數ival賦值

在宣告語句中,&和

*用於組成復合型別,在表示式中,他們是運算子

空指標空指標不指向任何物件,在試圖使用乙個指標之前,可以先檢查乙個它是否為空。

生成空指標的方法:

int *p = nullptr; //等價於第二個,nullptr是一種特殊型別的字面值,可以被轉換成任意其他型別的指標。

int *p2 = 0;  //直接將p2初始化為字面常量0

int *p3 = null;  //null 為預處理變數,它的值就為0,需要首先#include cstdlib

把int

變數直接賦值給指標是錯誤的操作,即使int變數的值恰好等於0也不行。

int zero = 0;

pi = zero; //錯誤:不能把int變數直接賦給指標

和其他變數一樣,訪問未經初始化的指標所引發的後果是無法**的,通常這一行為將會造成程式崩潰。

賦值和指標

和其他非引用的任何變數一樣,給指標賦值就是令它存放乙個新的位址,從而指向乙個新的物件。

賦值永遠改變的是等號左側的物件。

int i = 42;

int *pi = 0;  //pi被初始化,但是沒有指向任何物件

int *pi2 = &i;  //pi2被初始化,存有i的位址

int *pi3;  //如果pi3存放在塊內,則pi3的值無法確定

pi3 = pi2;  //pi2與pi3指向同乙個物件i

*pi2 = 50;  //pi2指向的i的值被改變,指標pi2並沒有改變

pi2 = 0;  //pi2的值被改變,現在pi2不指向任何物件了

其他指標操作

只要指標擁有乙個合法值,就可以用在條件表示式中,和採用算術值作為條件遵循的規則類似。任何非0指標對應的條件值都是true,0指標條件去false。

對於兩個型別相同的指標,可以用相等操作符(==)和不相等操作符(!=)來比較她們,比較的結果是布林型別。

void*指標

void*是一種特殊的指標型別,可用於存放任意物件的位址,該位址中到底是個什麼型別的變數並不了解。

void*指標能做的事情很有限:和別的指標比較、作為函式的輸入或輸出、賦給另外乙個

void*

指標。

不能直接操作

void*

指標所指的物件。

指標與引用的區別

★ 相同點:

1. 都是位址的概念;

指標指向一塊記憶體,它的內容是所指記憶體的位址;引用是某塊記憶體的別名。

★ 區別:

1. 指標是乙個變數,而引用僅是個別名;

2. 引用使用時無需解引用(*),指標需要解引用;

3. 引用只能在定義時被初始化一次,之後不可變;指標可變;

4. 引用沒有 const,指標有 const,const 的指標不可變;

5. 引用不能為空,指標可以為空;

6. 「sizeof 引用」得到的是所指向的變數(物件)的大小,而「sizeof 指標」得到的是指標本身(所指向的變數或物件的位址)的大小;typeid(t) == typeid(t&) 恒為真,sizeof(t) == sizeof(t&) 恒為真,但是當引用作為成員時,其占用空間與指標相同(沒找到標準的規定)。

7. 指標和引用的自增(++)運算意義不一樣;

8. 如果返回動態記憶體分配的物件或者記憶體,必須使用指標,引用可能引起記憶體洩漏;

★ 聯絡

1. 引用在語言內部用指標實現(const 指標?)。

2. 對一般應用而言,把引用理解為指標,不會犯嚴重語義錯誤。引用是操作受限了的指標(僅容許取內容操作)。

指標與引用

摘自 高質量c 程式設計 指標與引用,在more effective c 的條款一有詳細講述,我給你轉過來 條款一 指標與引用的區別 指標與引用看上去完全不同 指標用操作符 和 引用使用操作符 但是它們似乎有相同的功能。指標與引用都是讓你間接引用其他物件。你如何決定在什麼時候使用指標,在什麼時候使用...

引用與指標

引用就是物件的另乙個名字,在實際的程式中,引用主要用作函式的形式引數。引用是一種復合型別,通過在變數名前新增 符號來定義。復合型別是指用其他型別定義的型別。在引用的情況下,每一種引用型別都 關聯到 某一其他型別。引用必須用與該引用同型別的物件初始化。當引用初始化後,只要該引用存在,它就保持繫結到初始...

指標與引用

include iostream using namespace std void testref int i 10 引用不可以為空,他是乙個物件的別名 int ref i ref cout i 00824f1e mov dword ptr i 1 把i的位址傳入eax 並把eax指標的位址傳給re...