首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 中 const 關鍵字完整用法詳解

     編輯:關於C++

前言

C++ 繼承了 C 的基礎,並引入了許多強大的特性,其中 const 關鍵字是取代 C 時代 #define 宏常量的重要工具。掌握 const 的正確用法,不僅能提升程式碼的型別安全性,還能增強程式的健壯性與可維護性。本文將系統整理 const 的核心用法、常見陷阱與最佳實踐。

一、const 基本特性

1. 唯讀限定符

const 宣告的變數只能被讀取,任何嘗試修改的操作都會導致編譯錯誤:

const int i = 5;
int j = 0;
// i = j; // 錯誤:無法修改 const 變數
j = i; // 正確:可讀取 const 變數的值

2. 必須初始化

const 變數在宣告時必須立即初始化,否則編譯失敗:

const int i = 5; // 正確
// const int j;   // 錯誤:未初始化

3. 跨檔案引用

使用 extern 可在其他連結檔案中引用 const 常量,但不可再次賦值:

extern const int i;      // 正確:宣告外部常量
// extern const int j = 10; // 錯誤:常量不可重複賦值

4. 型別檢查優勢

相較於 #define 單純的文字替換,const 擁有明確的資料型別,編譯器能執行型別安全檢查:

#define I 10
const long &ref = 10; // 明確分配記憶體位址

char c1 = I;  // 無警告,但隱含型別轉換風險
char c2 = ref; // 編譯警告:可能發生截斷

5. 記憶體分配效率

const 定義的常量在程式執行期間僅有一份拷貝,而 #define 每次使用都會產生立即數拷貝:

#define STR "abcdefghijklmn"
const char str[] = "abcdefghijklmn";

printf(STR); // 每次呼叫皆分配記憶體
printf(str); // 僅首次分配,後續複用同一記憶體

6. 函數初始化支援

const 常量可由函數回傳值初始化,這對嵌入式系統(如 ROM 程式碼區)特別有用:

int getValue();
const int val = getValue();       // 一般初始化
const int &refVal = getValue();   // 參考繫結,可控制記憶體位置

二、const 常量真的不可修改嗎?

透過強制型別轉換,仍可繞過編譯器限制修改 const 變數(僅供理解原理,實務嚴禁使用):

const int i = 0;
int *p = (int*)&i;
*p = 100; // 強制修改,行為未定義

三、指標與 const 的組合規則

掌握「const 位於星號左側修飾指向內容,右側修飾指標本身」的口訣:

int val = 0;
const int *p1 = &val;     // 指向常量的指標,內容不可改
int * const p2 = &val;    // 常量指標,指標本身不可改
const int * const p3 = &val; // 指標與內容皆不可改

四、類別中的 const 成員

1. const 資料成員

  • 每個物件擁有各自的常量值,需在建構函數初始化列表中設定
  • 類別宣告中不可直接初始化
  • 若需全類別共用常數,建議使用 enum 或 static const
class A {
    const int size;           // 僅宣告
    enum { MAX_SIZE = 100 };  // 編譯期常數,可用於陣列大小
    int arr[MAX_SIZE];
public:
    A(int s) : size(s) {}     // 初始化列表賦值
};

2. const 成員函數

宣告於函數尾部,承諾不修改物件狀態:

class Stack {
    int count;
public:
    int getCount() const {    // const 成員函數
        // ++count;          // 錯誤:嘗試修改資料成員
        // pop();            // 錯誤:呼叫非 const 函數
        return count;
    }
};

五、函數參數與回傳值的 const 應用

1. 參數保護

  • 指標/參考參數加 const 可防止函數內部修改原始物件
  • 傳值參數無需 const(已自動複製)
  • 非內建型別輸入參數建議用 const T& 避免複製開銷
void func(const MyClass& obj); // 高效且安全
void func(int x);                // 內建型別傳值即可

2. 回傳值保護

  • 回傳 const 物件/參考可防止類似 (a*b)=c 的無意圖賦值
  • 多用於運算子多載(如 operator* 回傳新物件)
  • 一般函數不建議回傳 const 物件,會限制呼叫端操作
const Rational operator*(const Rational& lhs, const Rational& rhs) {
    return Rational(lhs.num()*rhs.num(), lhs.den()*rhs.den());
}
// (a*b) = c; // 編譯錯誤:無法賦值給暫時常量物件

六、const 使用建議總結

  1. 大膽使用:只要搞清語意,const 能帶來型別安全與最佳化提示
  2. 避免常見錯誤:勿將 const 變數賦值給非 const 指標/參考
  3. 參數優先用參考/指標:搭配 const 達成高效與保護雙重效果
  4. 成員函數盡量加 const:凡不修改狀態者皆應標記
  5. 慎用 const 回傳值:除非是運算子多載產生新物件,否則易造成介面不便

七、思考題解析

// 思考1:錯誤。const A* 指向常量,不可轉給 A*(會失去保護)
const A* c = new A();
A* e = c; // 編譯錯誤

// 思考2:正確。A* const 指標本身不可改,但指向內容可修改
A* const c = new A();
A* b = c; // 合法,複製指標值

// 思考3:錯誤。賦值運算子回傳 const A& 會導致 (a=b)=c 失敗
const A& operator=(const A& a); // 連續賦值會出錯
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved