const 是C++ 中常用的類型限定符,但我在工作中卻發現,許多人使用它僅僅是想當然,這樣有時也會用對,但在某些微妙的場合,可就沒有那麼幸運了。
究其實質原由,大多因爲沒有搞清const 類型限定符的本質。這裏我將對const 類型限定符進行一個分析,溯其本源究其本質,希望對大家理解const 有所幫助。
C++中爲什麼要引入 const
C++ 的作者當初是出於怎樣的目的引入(或稱保留) const 關鍵字的呢? 這是一個有趣又有益的話題,對理解 const 很有幫助。
1。大家知道,C++ 有一個類型嚴格的編譯系統,這使得C++ 程序的錯誤在編譯階段即可發現許多,從而使出錯率大爲減少,
也因此 成爲了C++ 與 C 相比有些突出優點的一個方面。
2。C 中很常見的預處理指令 #define VariableName VariableValue 可以很方便地進行值替換,這種替換在至少在以下三個方面
優點表現突出:
- 一是避免了意義模糊的數字出現,使得程序語義清晰流暢, 如下例: #define USER_NUM_MAX 108 。這樣就避免了直接使用數字108帶來的困惑。
- 二是可以很方便地進行參數的調整與修改。如上例,當人數由108變爲200時,在此改動一處就可。
- 三是提高了程序的執行效率。由於使用了預編譯器進行值替換,並不需要爲這些常量分配存儲空間,所以執行效率較高。
鑑於以上的優點,這種預定義指令的使用在程序中隨處可見。
3。說到這裏,大家可能會迷惑上述所講的1、2兩點同 const 說明符有什麼關係。好,請接着下看:
預處理語句雖然有些以上所述的許多優點,但它也有個比較致命的缺點。即,預處理語句僅僅只是簡單的值替換,缺少類型的檢測機制。
這樣的預處理語句就可能享受 C++ 嚴格類型檢查的好處,從而可能成爲引發一系列錯誤的隱患。
4。好了,第一階段結論好了:
結論: const 說明符推出的初始目的,就是爲了取代預編譯指令 #define ,在繼承其優點的同時消除它的缺點。
現在的它形式變成了:
const Tpye VariableName = VariableValue;
爲什麼 const 可以很好地取代預定義語句呢? 請看
1、首先,以const 說明符修飾的常量值具有不可變性。這是它可取代預定義語句的基礎。
2、第二,它也同樣可以避免意義模糊的數字出現,使得程序語義清晰的同時可以很方便地對參數進行調整與修改。
3、第三,C++ 編譯器一般不爲普通 const 常量分配存儲空間,而是將們保存在符號表中,這使得它真正成爲了一個編譯期間常量。
由於 沒有了存儲與讀內存的操作,這使得它的效率也很高。這是它取代預定義語句的重要基礎。
4、最後,const 定義也同一般普通的變量定義一樣,它會由編譯器對它進行類型的檢測。消除了預定義語句的隱患。
const 說明符使用情況分類詳析
1。const 說明符用於指針的兩種情況分析:
int a ;
const int *p ; // 指針類型爲 const int *, 指針指向類型爲 const int 。指針變量爲非 const 類型,但指向的的變量爲 const 類型
int *const p = &a ; // 指針類型爲int *const , 指針指向 int 。指針變量爲 const 類型,指向的變量爲 非const 類型
const 類型指針的轉換問題:
1.、從" const 指針類型 " 到 " 非const 指針類型 " 的轉換:
除了 const char * 指針類型 可轉換爲 char * 類型外(這是爲了對c語言的向下兼容) ,
任何的 const type1 * 都不可轉換爲 type2 * 類型。
2、從 " 非const 指針類型 " 到 " const 指針類型 " 的轉換:
這樣的轉換都是可以執行的。
2。const 說明符限定函數的傳遞值參數:
void Fun( const int Var);
分析:
上述寫法限定了參數Var不可在函數體內改變。而由值傳遞的特點可知,就算Var在函數體中改變了也不會影響到函數外部。
所以,此限定與函數的使用者無關,僅與函數的編寫者有關。
結論:最好在函數的內部進行限定,對外部調用者屏蔽以免引起困惑。如可改寫如下:
void Fun( int Var)
{
const int &VarAlias = Var;
.....
}
3。const 限定函數的返回值類型
const int Fun1();
const MyClass Fun2();
const int &Fun3();
cosnt int *Fun4();
const MyClass &Fun5();
const MyClass *Fun6();
分析:
上述寫法僅限定函數的返回值不可被改寫。
1.當函數返回爲內置類型的數據時,那已經是一個數值,那是必定不可改寫的,這時的const 可要可不要。但建議去掉。
2.當函數返回爲自定義類型的對象,這時的對象仍然可能包含可被賦值的數據成員,所以此時有意義。
3.如返回的是一個引用或是指針時,這種情況最爲常見,由地址變量的特點可知,適當使用const ,意義昭然。
4。const 限定類的成員函數
class ClassName
{
public:
int Fun() const;
.....
}
注意:
採用這種const 後置的形式是一種規定,也是爲了不引起混淆。在這個函數的聲明和定義中均要使用const,因爲const已經成爲類型信息的一部分。
獲得能力:可以操作常量對象。
失去能力:不能修改類的數據成員,不能在函數中調用其他不是const的函數。