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

C++ static 與 const 關鍵字深度辨析:儲存期、連結性、語義與陷阱

     編輯:VC 教學

static:一個關鍵字,三重身份

1. 控制區域變數儲存期:靜態儲存期

void Counter() {
    static int cnt = 0; // 僅初始化一次,儲存在 .bss/.data 段
    std::cout << ++cnt << '\n';
}
int main() { Counter(); Counter(); Counter(); } // 輸出 1 2 3
  • **生命週期** = 程式全程,**作用域** = 函數內部
  • 解決「函數內部狀態保持」需求,避免全域變數汙染名稱空間
  • 執行緒不安全(C++11 起初始化執行緒安全,但讀寫需自行同步)

2. 控制全域變數/函數連結性:內部連結

// File1.cpp
static int g_moduleState = 0;      // 僅本編譯單元可見
static void Helper() { ... }       // 僅本檔案可呼叫

// File2.cpp
// extern int g_moduleState; // 連結錯誤:找不到符號
  • 對應關鍵字 extern(外部連結,預設)
  • 現代 C++ 偏好 **匿名命名空間** 替代:namespace { int x; }

3. 類別靜態成員:屬於類別,不屬於物件

class Widget {
public:
    static int s_count;     // 宣告
    static void Reset() { s_count = 0; }
private:
    static const int MAX = 100; // 整數常數可類內初始化
};
int Widget::s_count = 0;    // 定義(在 .cpp 中,分配儲存空間)
  • 靜態資料成員:單一實體,全程存在,Widget::s_count 存取
  • 靜態成員函數:無 this 指標,僅能存取靜態成員,Widget::Reset() 呼叫
  • 初始化順序:跨編譯單元靜態物件初始化順序**未定義** → 使用「構造時初始化」單例模式避免

static 總結表

對象儲存期連結性作用域
區域 static 變數靜態(程式全程)無連結區塊內
全域 static 變數/函數靜態內部連結檔案內
類別 static 成員靜態外部連結(需定義)類別域

const:不只是「常數」

1. 基本語義:唯讀語義

const int MAX = 100;        // 編譯期常數,內部連結(C++)
const double PI = 3.14159;  // 取址時才分配儲存空間

2. 指標與 const 的四種組合


const int* p1;      // 指向 const int:資料不可改,指標可改
int* const p2;      // const 指向 int:指標不可改,資料可改
const int* const p3; // 指向 const int 的 const 指標:雙重不可改
int const* p4;      // 同 p1(const 在 * 左側修飾資料)

**口訣**:* 左邊有 const → 資料唯讀;* 右邊有 const → 指標唯讀。

3. 參數傳遞:const 參考

void Process(const BigObject& obj); // 避免複製,承諾不修改
void Process(BigObject&& obj);      // C++11 右值參考,移動語義

4. 成員函數 const:語義契約

class Date {
    int y, m, d;
public:
    int Year() const { return y; }      // 承諾不修改 *this
    void SetYear(int v) { y = v; }      // 非 const
    // 錯誤:int Year() { return y++; } // 修改了物件
};
  • const 物件**只能呼叫 const 成員函數**
  • mutable 成員可在 const 函數中修改(快取、鎖、日誌)

5. const 與 static 交互

static const int CLASS_CONST = 42; // 類內靜態常數,C++17 起可 inline 定義
constexpr int COMPILE_TIME = 3*4;  // 編譯期常數,隱含 const、static、內部連結

經典陷阱大全

代碼問題解釋
const int* p = &x; *p = 5;編譯錯誤資料唯讀
int* const p = &x; p = &y;編譯錯誤指標唯讀
char* p = "literal";未定義行為 (C++11 起非法)字面常數區唯讀,應 const char*
static int x = f();跨檔初始化順序未定義改用函數靜態區域變數單例
const_cast(p)->Modify();若原物件真為 const → UB僅用於舊 API 互操作,極度謹慎

總結

  • static:決定「活多久」(靜態儲存期)與「誰看得到」(內部連結)
  • const:決定「能不能改」(唯讀語義)與「介面契約」(const 正確性)
  • 現代 C++:constexpr 取代宏常數,inline static 簡化靜態成員定義,const 參考/指標貫穿介面設計
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved