1.指針初始化和賦值操作的約束
對指針進行初始化或賦值只能使用以下四種類型的值:
1.0 值常量表達式,例如,在編譯時可獲得 0 值的整型const 對象或字面值常量 0。
2.類型匹配的對象的地址。
3.另一對象末的下一地址。
4.同類型的另一個有效指針。
把 int 型變量賦給指針是非法的,儘管此 int 型變量的值可能爲 0。但允許把數值 0 或在編譯時可獲得 0 值的const 量賦給指針:
int ival; int zero = 0; const int c_ival = 0; int *pi = ival; // error: pi initialized from int value of ival pi = zero; // error: pi assigned int value of zero pi = c_ival; // ok: c_ival is a const with compile-time value of 0 pi = 0; // ok: directly initialize to literal constant 0
除了使用數值0或在編譯時值爲 0 的 const 量外,還可以使用 C++ 語言從 C 語言中繼承下來的預處理器變量NULL(第 2.9.2 節),該變量在 cstdlib 頭文件中定義,其值爲 0。如果在代碼中使用了這個預處理器變量,則編譯時會自動被數值 0 替換。因此,把指針初始化爲NULL 等效於初始化爲 0 值:
// cstdlib #defines NULL to 0 int *pi = NULL; // ok: equivalent to int *pi = 0;
C++ 提供了一種特殊的指針類型 void*,它可以保存任何類型對象的地址:
double obj = 3.14; double *pd = &obj; // ok: void* can hold the address value of any data pointer type void *pv = &obj; // obj can be an object of any type pv = pd; // pd can be a pointer to any type
2.指針和引用的比較
雖然使用引用(reference)和指針都可間接訪問另一個值,但它們之間有兩個重要區別。
1.在於引用總是指向某個對象:定義引用時沒有初始化是錯誤的。
2.賦值行爲的差異:給引用賦值修改的是該引用所關聯的對象的值,而並不是使引用與另一個對象關聯。引用一經初始化,就始終指向同一個特定對象(這就是爲什麼引用必須在定義時初始化的原因)。改變指針的值就改變了他指向的內存空間,而改變引用的值是改變了他綁定的內容
考慮以下兩個程序段。第一個程序段將一個指針賦給另一指針:
int ival = 1024, ival2 = 2048; int *pi = &ival, *pi2 = &ival2; pi = pi2; // pi now points to ival2
賦值結束後,pi 所指向的 ival 對象值保持不變,賦值操作修改了 pi 指針的值,使其指向另一個不同的對象。現在考慮另一段相似的程序,使用兩個引用賦值:
int &ri = ival, &ri2 = ival2; ri = ri2; // assigns ival2 to ival
這個賦值操作修改了 ri 引用的值 ival 對象,而並非引用本身。賦值後,這兩個引用還是分別指向原來關聯的對象,此時這兩個對象的值相等。