const指針和指向常量的指針
先看下面六種寫法:
1. const int p;
2. const int *p;
3. int const* p;
4. int * const p;
5. const int * const p;
6. int const * const p;
那麼我們應該怎麼區分上面的寫法到底是指向常量的指針還是const指針(表示指針本身是常量)呢?
一個簡便方法:從由往左讀,遇到p就替換爲“p is a”,遇到*就替換爲“point to”,其餘不變。
下面我們來一個一個看:
1. const int p; // p is a int const. p是一個int型常量 這個很簡單
2. const int *p; //p is a point to int const. p是一個指針,指向int型常量。即p是一個指向int型常量的指針。
3. int const *p; //與2相同 const int 和 int const 是一樣的意思。《C++ primer》中採用第一種寫法。
4. int * const p; // p is a const point to int. p是一個指向int的const指針
5. const int * const p; //p is a const point to int const. p是一個指向int型常量的const指針。
6. int const * const p; //同5
知道怎麼區分const指針和指向常量的指針,我們再來看看它們的定義。
指向常量的指針(point to const)不能用於改變其所指對象的值。 比如:
const double pi = 3.14; // pi是一個常量,不能改變它的值
const double *cptr = π //cptr指向pi,注意這裏的const不能丟,因爲普通指針不能指向常量對象,即,不能用非const變量初始化指向常量的指針.
*cptr = 3.33; //錯誤,試圖改變所指對象的值。不能改變指針所指對象的值
cout << cptr << endl;//輸出cptr的值
//雖然不能改變其所指對象的值,但是它可以指向別的常量對象
//這樣的話 指針的值(也就是存放在指針中的那個地址)也會改變 比如:
cosnt double pi2 = 6.28;
cptr = &pi2; //正確 *cptr爲6.28
cout << cptr << endl; //cptr的值變了
const指針表示指針本身是一個常量。 由於指針是對象,因此就像其他對象一樣,允許把指針本身定爲常量。cosnt指針必須初始化,並且一旦初始化,const指針的值就不能改變了。const指針的值到底是什麼?其實就是存放在指針中的地址,這個地址是一個對象的地址。
把*放在const前面就表示指針是一個常量,這樣的書寫形式意味着不變的是指針本身的值而不是指向的對象的值(內容)。也就是說,那個地址不能再變了,但是我們可以改變那個地址上存放的內容。比如:
int i = 42;
int * cosnt p = &i; //p是一個const指針
cosnt int i2 = 44;
p = &i2; //錯誤 不能改變p的值
//雖然不能給p賦值,也就是不能改變p的值,但是我們可以改變p所指的對象的內容。比如:
*p = 46; //正確 此時i爲46
指針本身是一個常量(即const指針)並不意味着不能通過指針修改其所指對象的值,能否這樣做完全依賴於所指對象的類型。比如,
const double pi = 4.4;
const double *const pip = π //pip是一個指向常量對象的const指針
pip是一個指向常量的常量指針,則不論pip所指的對象值還是pip自己存儲的那個地址都不能改變。相反,上例中的p指向的是一般的非const整型,所以p可以修改i的值。
完整代碼:
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
const int b = 11;
const int *p2 = &b; //指向常量的指針 底層const 不能改變p2的所指對象的值 但是可以改變p2的值(即指針的指向) 前提是仍然指向一個常量
cout << *p2 << endl; //11
cout << p2 << endl; //0x72fe38
const int c = 22;
p2 = &c;
cout << *p2 << endl; //22
cout << p2 << endl; //0x72fe34地址發生了改變
int i = 9;
int *const p1 = &i; //指針是一個常量(即常量指針)頂層const 不能改變p2的值(存放在p2中對象的地址) 但是可以改變對象的內容
cout << p1 << endl; //0x72fe3c 這個地址不會再改變了
*p1 = 88;
cout << i << endl; //88
cout << *p1 << endl; //88
cout << p1 << endl; //0x72fe3c
return 0;
}
對於指針來說,頂層const表示指針本身是一個常量,底層const表示指針所指的對象是一個常量。所以const指針是頂層const,而指向常量的指針是底層const。