const 是 C++ 型別系統的基石,正確使用能讓編譯器協助發現邏輯錯誤、優化程式碼、表達設計意圖。本文涵蓋基本宣告、指標與常量指標、函式參數/回傳值、類別成員、mutable 與 const_cast 進階用法,並釐清常見誤區。
const int MAX = 100; // 編譯期常數,內部連結(C++),建議替代 #define
extern const int GLOBAL_MAX; // 外部連結,跨檔共用,需在 .cpp 定義
const int arr[] = {1,2,3}; // 常數陣列,編譯器配置記憶體,不可作為編譯期常數運算
⚠️ const int const* p:對 int 重複套用 const,編譯器警告 C4114。
| 宣告 | 口訣 | 指標可改向 | 指向值可修改 | 別名 |
|---|---|---|---|---|
const int* pint const* p | 指向 const 的指標 | ✅ | ❌ | Pointer to Const |
int* const p | const 指標 | ❌ | ✅ | Const Pointer |
const int* const p | 指向 const 的 const 指標 | ❌ | ❌ | Const Pointer to Const |
💡 記憶法:**從右向左讀**,const 修飾其右側緊鄰元素。
void Func(const int x); // x 本身就是副本,const 只是防止函式內修改參數變數,對呼叫端無影響
void ReadOnly(const BigObj& obj); // 避免拷貝,承諾不修改
void ReadOnlyPtr(const BigObj* ptr); // 同樣語意
// 唯有 const 參考能綁定暫時物件
void Func(const string& s);
Func("temp"); // ✅ 合法,延長暫時物件生命週期
// Func(string& s); Func("temp"); // ❌ 非 const 參考不可綁定暫時物件
const int 無意義(回傳的是右值,不可修改)。const Class 禁止左值操作:Func() = obj; 編譯錯誤,防止 GetObj().Modify() 修改暫時物件。
const char* Func1(); // 回傳指向 const char 的指標,呼叫端不可修改內容
char* const Func2(); // 回傳 const 指標(指標本身不可修改),極少用
const char* const Func3(); // 雙重 const,回傳 const 指標指向 const 資料
Class(int v): m_constVal(v) {}。static const int 整數型別可在類別內初始化(C++11 起所有字面型別皆可)。
class Widget {
int m_val;
mutable int m_cacheHits; // 可在 const 函式修改
public:
int GetVal() const { ++m_cacheHits; return m_val; } // ✅ 承諾不修改邏輯狀態
void SetVal(int v) { m_val = v; } // 非 const
};
const Widget cw;
cw.GetVal(); // ✅
// cw.SetVal(1); // ❌ 編譯錯誤
const 放在參數列表後:RetType Func(params) const。mutable 成員、不可呼叫非 const 成員函式。mutable:標記「邏輯上不影響物件可觀測狀態」的成員(快取、鎖、統計計數)。建構時物件尚未形成「常態」,解構時需修改資源釋放狀態。
const int CI = 100;
int* p = const_cast(&CI); // C++ 風格
// *p = 200; // ⚠️ 未定義行為!原物件為真正 const,修改導致 UB
const 的物件屬於未定義行為(編譯器可能將其放入唯讀段、常數摺疊等)。
char* s1 = "hello"; // ❌ C++11 起棄用,字串字面值為 const char[]
const char* s2 = "hello"; // ✅ 正確
char s3[] = "hello"; // ✅ 陣列複製,可修改 s3[0]='H'
const**。this 的成員函式**一律加 const**。const**。mutable 區分「邏輯常態」與「實體常態」。const_cast 修改真正的常數物件。const(無意義且誤導)。