C Primer 筆記四 初識指標和引用

2021-09-30 20:23:03 字數 3274 閱讀 1207

引用

引用是某個已存在物件的別名,實現了對其他物件的間接訪問。引用本身不是物件。其定義如下:

int ival = 1024;

int &refval = ival;

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

對引用進行操作,實際上是對引用所繫結的物件進行操作。

refval = 2048; 			// 實際上是把2048賦值給refval所繫結的物件ival

// 以引用作為初始值,實際上是把引用繫結的物件作為初始值

int ival2 = refval; // 用ival初始化ival2

int &refval2 = refval; // refval2繫結到ival上

因為引用本身不是物件,所以不能定義引用的引用,且引用只能繫結到物件上,而不能與某個字面值表示式的結果繫結在一起。引用的型別要和與之繫結的物件嚴格匹配。

double dval = 3.14;

// 下面的操作將引發錯誤

// error: invalid initialization of non-const reference of type 'int&' from an rvalue of tye 'int'

int &refval3 = dval;

double &dref = &dval;

dref = refval2; // 實際上是將ival的值賦值給dval,執行隱式轉化

指標

指標是指向另外一種型別的復合型別,同樣實現了對其他物件的間接訪問。不同於引用的是,指標本身就是乙個物件。指標的定義如下:

int ival = 44;

int *p1, *p2 = &ival; // 使用取位址符 & 獲取物件的位址

因為指標本身就是乙個物件,所以允許對指標賦值和拷貝,且在指標的生命週期內,指標可以先後指向幾個不同的物件,對指標進行賦值就令指標指向了乙個新的物件。並且,指標無需在定義時賦初值,塊作用域內定義的指標若沒有被初始化,將擁有乙個不確定的值。

指標的值是乙個位址,且應該是下面4種狀態之一:

指向乙個物件;

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

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

不屬於上面3種情況,為無效指標;

試圖拷貝或者訪問乙個無效指標都將引發錯誤,且編譯器並不檢查此類錯誤。建議初始化所有的指標,未確定指向物件時應該初始化為nullptr或者0.

因為引用本身不是物件,沒有實際位址,因此不能定義引用的指標。但指標是物件,所有存在對指標的引用。

指標的型別和它所指的物件嚴格匹配。把int變數直接賦值給指標是錯誤的操作,即便int的值恰好為0。

int *iptr = &ival;	// 正確,iptr指向ival

iptr = &ival2; // 現在iptr指向ival2

// 下面的操作將引發錯誤

// error: cannot convert 'double' to 'int*' in initialization.

int *iptr1 = &dval;

ival2 = 0;

// 下面的操作將引發錯誤

// error: invalid conversion from 'int' to 'int*'

int *iptr2 = ival2;

//error: invalid conversion from 'int' to 'int*'

iptr2 = 32;

// ok

iptr2 = 0;

使用別名可以直接訪問引用所繫結的物件,而要訪問指標指向的物件,必須使用解引用符(*):

std::cout << *iptr << std::endl;	// 輸出iptr指向物件ival2的值

std::cout << iptr << std::endl; // 輸出iptr指向物件ival2的位址

*iptr = 32; // 把32賦值給iptr指向的物件ival2

空指標表示不指向任何物件,可以使用下面的方法來生成空指標:

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

int *ptr1 = null; // 等價於 int *iptr1 = 0;

// null為預處理變數,定義在cstdlib標頭檔案中,null的值為0

int *ptr2 = nullptr; // c++11引入的方法,nullptr是乙個指標字面值

如果指標擁有乙個合法值,則可以將指標用在條件表示式中。任何非0指標對應的條件值都為true

int ival = 1024;

int ival1 = 2048;

int *iptr = 0;

int *iptr1 = &ival;

if (iptr)

if (iptr1)

對兩個指標進行比較,若存放位址相同,則它們相等;反之不相等。

if (iptr == iptr1) 

int *iptr2 = 0;

if (iptr1 == iptr2)

它們都為空;

兩個指標指向相同的物件;

void*指標是一類特殊的指標,可存放任意物件的位址,其位址的物件的型別是不確定的,因此不能直接操作void*所指向的物件。void*所能進行的操作有:

和別的指標進行比較;

作為函式的輸入或輸出;

賦值給另外乙個void指標。

double dpi = 3.14;

double *dptr = &dpi;

void *vptr = &dpi; // dpi可以是任意型別的物件

vptr = dptr; // vptr可以存放任意型別的指標

需要注意的是,void型別既無操作也無值,不能定義乙個void型別的變數,因此也不可以有void型別的引用。

C Primer(四)陣列和指標

陣列定義中的型別名可以是內建型別或者類型別,除引用之外,陣列元素的型別還可以是任意的復合型別。沒有所有元素都是引用的陣列 陣列的維數必須用值大於1的常量表示式定義。此常量表示式只能包含整型字面值 列舉常量或者用常量表示式初始化的整型const物件。非const變數以及要到執行時才知道其值的const...

C primer筆記 指標

1 指標存放某個物件的位址,要想獲取該位址,需要使用取位址符 操作符 定義指標型別的方法將宣告符寫成 d的形式,其中d是變數名。引用不是物件,沒有實際位址,不能定義指向引用的指標 1 指向乙個物件 2 指向緊鄰物件所佔空間的下乙個位置 3 空指標,意味著指標沒有指向任何物件。4 無效指標,也就是上述...

C Primer 筆記十二 初識 vector

標準庫型別vector表示型別相同的物件的集合,因之可以容納其他物件,也被稱作容器 container 引用不是物件,因此不存在引用的 vector 同 string 一樣,vector 也是對陣列的某種抽象。初始化 vector 是c 的乙個類模板而非型別,編譯器根據模板建立類或者函式的過程稱為例...