C++中const的“就近原則”
在做題的時候,編譯時經常會遇到關於const的坑,如果在平時不是常用的話就會很容易忘記,在這裡整理一下const的“就近原則”的筆記。
指標
要理解就近原則首先要明白指標。
指標(pointer),可以看作指向(point to)。與引用類似,實現了對其他物件的間接訪問。
但有兩個不同之處:
1.指標本身就是一個物件,允許對指標賦值和拷貝,並且指標在週期內可以先後指向幾個不同的物件(除非是const指標)
const指標是指標變數的值一經初始化,就不可以改變指向,初始化是必要的。其定義形式如下:
int * const pTwo; //指向整形的常量指標 ,它不能在指向別的變數,但指向(變數)的值可以修改。(結合之後會說的就近原則理解記憶。)
2.指標無需在定義時賦初值(若未初始化,它將有一個不確定得值)。
簡單示例
{
int a = 0;
int b = 1;
int* const p1 = &a; //p1是指向int型資料的const指標,指向不可改變。
int* (const p11) = &a; //p11與p1相同。
const int *p2 = &a; //p2是指向int型資料的指標,指向可以改變,
//但不可以通過p2改變指向地址上的值。
const int(*p22) = &a; //p22與p2相同。
const int* const p3 = &a; //p3是指向in型資料的const指標,不能通過p3改變指向地址上的值。
p1 = &b; //報錯(指標指向不能被修改)
*p1 = b;
p2 = &b;
*p2 = b; //報錯(指標指向的內容不能被修改)
p22 = &b;
*p22 = b; //報錯(指標指向的內容不能被修改)
p3 = &b; //報錯(指標指向不能被修改且指標指向的內容不能被修改)
*p3 = b; //報錯
}
讀const指標的方法,我們可以學習《C++Primer》上 P56的方法,也就是“從右往左讀”。
int errNumb = 0;
int *const curErr = &errNumb;
const double pi = 3.1415;
const double *const pip = π
此例中,從右往左,離curErr最近的是const,意味著curErr本身是一個常量物件,繼續往左看,下一個符號*和int表明curErr是一個指向int型別的指標——結合起來curErr就是一個常量指標,指向不可變,但可通過其本身改變指向地址上的值。
指標pip同理,可以得知:pip是一個指向const double的const指標,指向和指向地址上的值不可變。
const* ———————————修飾指標
const int*——————const修飾指標指向的物件, int * const
就近原則
就近原則我們可以在K & R 《The C Programming Language》(2nd)
A.8.6.1 Pointer Declarators
In a declaration T D where D has the form
- type-qualifier-listopt D1
and the type of the identifier in the declaration T D1 is
type-modifier T,'' the type of the identifier of D is
type-modifier type-qualifier-list pointer to T.’’ Qualifiers
following * apply to pointer itself, rather than to the object to
which the pointer points.
const char **s;
對於以上的宣告,以*號界定,開始讀:
以最右邊第一個 * 號開始,形式為:
const char ** | s
最右面第一個s前沒有修飾符,可以改變指標指向;s是指向const char **的指標(const char *就是指標),因此s也就是指向指標的指標;
再看第二個* 號,形式為:
為const char * | *s
由於*s前沒有修飾符,因此(*s)其值是可以改變的;
最後看const char *,類似於前面的const int *p1,因此表示該指標(***s)指向的(此處為字串)為常量,其值不可改變;
測試:
const char *fmt = "hello";
const char **s = &fmt;
*s++; //正確,指向改變了
(*s)++; //正確,指向的地址上的值,可以改變值
(**s)++; //報錯,指向的地址上的值不可改變
**s++;