1. 程式人生 > >透徹理解C++中const的含義

透徹理解C++中const的含義

關於const修飾變數、引數、返回值、成員函式不同的意義,網上有很多講解的,這裡不再贅述。在Dan Saks的一篇講解const的文章中非常清楚的從編譯器角度講了const的含義,本文只做一定的總結,原文參考http://blog.csdn.net/bianbian17556231/archive/2010/03/20/5398276.aspx
先看一個例子:

typedef char* VP;
const char *data[3] = {"I","Love","u"};      (1)
const VP data1[3] = {"I","Love","u"};       (2)

data[1] = "hate"
; //能正常修改 data1[1] = "hate"; //編譯器報錯,提示data1[1]是無法修改的左值

根據編譯器報錯的提示資訊,你可能猜到了在(2)式中的指標變為了常量指標,而(1)沒有改變。那為什麼會造成這種情況呢,這得從編譯器的角度來說明變數的申明順序問題。
1)對c和c++中的宣告做透徹分析,之前我們覺得不就一個宣告嘛,就是定義一個變數而沒有初始化嘛,有啥好講的。我之前也是這樣不求甚解,自從看了Dan Saks的文章後,我才明白專家之所以能成為專家是有道理的。。。
c和c++中宣告包含零個或者多個宣告說明符,和一個宣告符
例如:static unsigned long int *x[N];
static unsigned long int :宣告說明符
*x[N] :宣告符
a) 一個宣告符就是被宣告的名稱,可能還伴有操作符,如,(),[],&等,以本例為例,*

表示x是一個指標,[]表示序列, *x[N]表明x是含有N個指標的序列。
可能基礎比較弱的人一直分不清楚指標陣列和陣列指標,以及返回指標的函式和函式指標怎麼寫。其實與運算子一樣,操作符也是有優先順序的,在本例中[]的優先順序要比*的優先順序高,所以首先其是一個序列,然後才宣告序列中的元素是指標。而(*x)[N]中()的優先順序比[]的優先順序高,所以首先確定了其是一個指標。

b)宣告說明符包含型別說明符和與型別無關的說明符,分清楚這個對於理解例子中的兩個例子為什麼會出現不同的情況至關重要。注意在1)式中char是型別說明符,而const是與型別無關的說明符,所以1)式中const並不會修飾變數data,應該理解為指向const char的指標序列,而不是指向char的const指標序列。。

c)宣告說明符在一個宣告中出現的順序並不重要,如:

const void *data[N];
void const *data[N];

這兩者實際上是等價的,但是要注意對於指標的宣告是從右到左來看的,所以對於在對指標的宣告說明符中,正確的寫法應該將const放在型別說明符的右邊。如:

T const *p
T* const p

上面的式子中表示指向const T的指標,而下面的式子修飾了操作符*則表示指向T型別的const指標,說以對於最開始的問題中的2)按照正確的寫法應該是:

VP const data1[3] = {"I","Love","u"};
展開:
char* const data1[3] = {"I","Love","u"};

這樣對照剛剛的講解,現在是不是就能理解為什麼data1序列中的指標為const型別了。
d)補充說明,良好的程式設計習慣有時來源於對原理的透徹理解。如很多人會這樣寫對一個指標的宣告

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

理解了上面對變數宣告說明符和操作符的講解,相信應該清楚了為什麼要推薦下面的這種寫法了吧。
本篇部落格只是對Dan Saks的文章按照個人的理解做的總結,如有錯誤,歡迎給出指正。