引用
引用是某個已存在物件的別名,實現了對其他物件的間接訪問。引用本身不是物件。其定義如下:
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 的乙個類模板而非型別,編譯器根據模板建立類或者函式的過程稱為例...