1. 程式人生 > >C++ 中變數宣告中 const 用法

C++ 中變數宣告中 const 用法

一直以來對 C++ 中的 const 說明符理解不夠清晰,尤其是在變數宣告時處於何種位置起到何種作用,分辨不清。

現在花費一些時間專門理清其中的關係,明白其中的道理之後,就再也不會混淆了。文中內容主要參考了這篇譯文

1. 幾個概念

static unsigned long int *x[N]; 為例,說明幾個概念

  • 宣告符:一個宣告符就是被宣告的名稱,可能伴有操作符和識別符號,這裡為 *x[N]
  • 操作符:如 *, [], (), 和(C++中的) &. 正如你所知的,宣告中的符號 * 表示“指標”,[] 表示 “序列”;
  • 識別符號:一個宣告符可能包含不止一個識別符號。宣告符 *x[N]
    包含兩個識別符號,xN。只有其中一個識別符號是被宣告的,而且被稱為是宣告符ID,其餘的必須在這之前就被宣告過。舉例,*x[N] 中的宣告符ID是 x
  • 說明符:可以包括型別說明符,如 int, unsigned ,他們也可以是儲存類說明符,如 externstatic。在C++中,他們也可以是函式說明符,如 inlinevirtualconstvolat 關鍵詞都是型別說明符。

現在可以說,變數宣告語句 static unsigned long int *x[N]; 是由宣告符和說明符來組成的。其中宣告符由操作符和識別符號組成,說明符可以同時含有型別說明符、儲存類說明符等。

2. 解析順序

所謂的解析順序,我理解分為兩個部分,宣告符說明了是一個什麼東西,說明符給出了這個東西的一些性質。對宣告符來說,解析順序決定了這個東西屬於什麼大類,什麼小類,說明符不區分順序,給出了這個東西在不同方面的屬性。

2.1 操作符解析順序

可以按照這個規則來決定解析順序:離識別符號ID越近,越決定了目標先是什麼,距離相等情況下操作符優先順序越高越先解析。

舉例來說,*x[N]*[] 離識別符號ID x 的距離相等,按照 C++ 符號優先順序圖表進行解析, [] 的優先順序比 * 更高,因此宣告符 *x[N] 表明 x 是一個優先於指標的序列,也就是說,它首先是一個序列,其次序列中的每個元素是一個指標。如果想要變換解析順序,可以應用 ()

來提高解析級別,例如 (*x)[N] 表示為一個指向序列為 N 的指標。

2.2 說明符解析順序

宣告說明符在一個宣告中出現的順序並不重要。比如 const unsigned static intstatic unsigned int constint const unsigned staticconst int static unsigned,只不過通常大家有一套預設的書寫順序。

2.3 constvolatile

能出現在宣告符中的宣告說明符只有 constvolatile。當出現在宣告符中時,可以認為其修飾的物件變成了操作符,並且不能交換 constvolatile 在宣告中的順序(不能交換constvolatile與操作符*的順序)。例如 int const *aa 宣告為指向 const int 的指標,而 int *const aa 宣告為指向 int 的 const 指標。

2.4 最終的解析順序

參考文章中總結到:

C++基本上是按從頭到尾、從左到右的順序來讀,但是指標的宣告,從某種意義來講卻是倒著的。指標的宣告是從右到左來看。把 const 放在其他型別說明符的右邊,可以嚴格的從右到左來看指標宣告,還可以把 const 從“右邊的”位置提出來,如: T const *p; 把 p 宣告為“指向 const T 的指標”,非常準確,同樣: T *const p; 把 p 宣告為“指向 T 的 const 指標”,也能正確的理解。

按照我自己的理解,可以按照先確定是什麼東西(宣告符),再看這個東西的性質(說明符)順序來確定。

以上面例子來說,T const *p 先確定是一個指標,再看這個指標是關於 const T 型別的,也就是“指向 const T 的指標”;T *const p 先確定時一個 const 指標,再看這個 const 指標是關於 T 型別的,也就是“指向 T 的 const 指標”。

3. 宣告風格

  • 當把變數宣告語句分成說明符和宣告符兩大部分之後,可能比較好理解文中給出的陳述:

const int* p; 而不是 const int *p;

  • 依照參考文章中對宣告順序的理解,給出的另一個建議:

const void *vectorTable[] (3) void const *vectorTable[] (4) 大多數C和C++程式設計師更喜歡把const和volatile寫在其他型別的說明符的左邊,同(3)。而我更喜歡把const和volatile寫在右邊,如(4),而且強烈推薦這樣寫。

參考連結