const 基礎:讓變數成為常量
const int MAX = 100; // 必須初始化,之後不可修改
// MAX = 200; // 編譯錯誤
指標與 const:兩個獨立維度
指標宣告中有兩個可被 const 修飾的實體:**指標指向的物件** 與 **指標本身**。
情況 1:指向常量的指標
const int *p1; // 或 int const *p1
int const *p2; // 相同
// 讀法:p1 是一個指標,指向 const int
// 限制:不能通過 p1 修改物件值(*p1 = 10 錯誤)
// 允許:修改指標指向 (p1 = &other)
情況 2:常量指標
int *const p3 = &a;
// 讀法:p3 是一個 const 指標,指向 int
// 限制:不能修改指標指向 (p3 = &other 錯誤)
// 允許:通過指標修改物件 (*p3 = 20 正確)
情況 3:指向常量的常量指標
const int *const p4 = &a;
// 讀法:p4 是 const 指標,指向 const int
// 雙重限制:指向不可改、物件不可改
右左讀法:一招搞定所有複雜宣告
- 找到識別符(變數名)。
- 向右讀到結尾,再向左讀到開頭。
- 遇到
const 說明其修飾的實體。
const int *const p;
// ↑ 識別符 p
// 向右:const → p 是 const
// 向左:* → p 是指標
// 向左:const int → 指向 const int
// 結果:p 是 const 指標,指向 const int
函數參數與返回值的 const 實戰
| 宣告 | 含義 | 典型用途 |
void f(const T&) | 參考參數不可修改 | 大型物件唯讀傳遞(標準做法) |
void f(T* const) | 指標參數本身不可修改 | 罕見,參數傳值本身就是副本 |
void f(const T*) | 指向不可修改物件 | C 風格 API 唯讀緩衝區 |
const T& f() | 返回常量引用 | 避免拷貝,防止修改內部狀態 |
T* const f() | 返回常量指標 | 極少用,返回值本身是右值 |
成員函數的 const:物件不可修改契約
class Widget {
int value;
public:
int get() const { return value; } // ✅ 承諾不修改 *this
void set(int v) { value = v; } // 非 const
void setConst(int v) const { value = v; } // ❌ 編譯錯誤
mutable int cache; // 可變成員,即使在 const 函數中也可修改
int getWithCache() const {
if (!cached) { cache = compute(); cached = true; }
return cache;
}
private:
mutable bool cached = false;
};
const 多載:同名函數區分 const/非 const 物件
class Container {
vector<int> data;
public:
int& operator[](size_t i) { return data[i]; } // 非 const 版本:可修改
const int& operator[](size_t i) const { return data[i]; } // const 版本:唯讀
};
Container c;
c[0] = 10; // 呼叫非 const 版本
const Container cc = c;
int x = cc[0]; // 呼叫 const 版本
// cc[0] = 20; // 編譯錯誤
現代 C++:constexpr、constinit、consteval
| 關鍵字 | 含義 | 適用場景 |
constexpr | 編譯期可計算,隱含 const | 常量表達式、編譯期函數、模板參數 |
consteval (C++20) | 強制編譯期執行 | 必須在編譯期完成的計算(如哈希、反射) |
constinit (C++20) | 靜態儲存期變數強制靜態初始化 | 避免靜態初始化順序災難 |
常見誤區對比表
| 錯誤認知 | 正確理解 |
const int *p 表示指標不可改 | 表示**指向的 int** 不可改;指標可改 |
函數參數 T* const p 有意義 | 參數按值傳遞,const 只影響函數內部,對調用者無影響 |
const 物件不能呼叫非 const 函數 | 正確;但可透過 mutable 或 const_cast(極度謹慎)繞過 |
constexpr 只是加強版 const | constexpr 保證編譯期可計算,const 僅承諾運行期不修改 |
總結
- 用**右左讀法**精準解讀多層
const 指標宣告。
- 函數參數:大型物件用
const T&,C API 緩衝區用 const T*,指標參數本身加 const 通常無意義。
- 成員函數**盡可能加
const**,配合 mutable 處理邏輯常態(快取、鎖、統計)。
- 新專案優先用
constexpr/consteval 將不變值推向編譯期,提升效能與安全性。
- 上一篇文章: C++ 參考類型完全指南:別名機制、const 參考延長壽命與函數參數最佳實踐
- 下一篇文章: C/C++ 指標學習兩大經典範例:交換排序與函數傳遞深度剖析
Copyright ©
程式碼之家 All Rights Reserved