C++ 中的 static 有兩大使用語境:
// file1.cpp
static int g_count = 0; // 僅在本文件可見
extern 訪問,避免命名衝突;void foo() {
static int callTimes = 0; // 僅初始化一次
++callTimes;
std::cout << callTimes;
}
static void internalHelper() { /* ... */ } // 僅本文件可見
class Counter {
public:
Counter() { ++s_count; }
static int getCount() { return s_count; }
private:
static int s_count; // 僅聲明
};
// 必須在類外定義並初始化(C++17 前)
int Counter::s_count = 0;
Counter::s_count 或 obj.s_count(推薦前者);public/protected/private,受訪問控制約束;static inline int s_count = 0; 類內定義初始化。class Math {
public:
static int add(int a, int b) { return a + b; } // 無 this 指針
};
Math::add(1, 2); // 類名調用
this 指針**,只能訪問靜態成員;const/volatile/virtual;代碼區 全局數據區 ← static 變量(全局/局部/類靜態成員)均在這裡 堆區 ← new/malloc 動態分配 棧區 ← 函數參數、局部非靜態變量
靜態存儲區的數據**不隨函數/對象銷毀而釋放**,程序結束前一直存在。
| 場景 | 建議 |
|---|---|
| 模塊內部狀態 | 優先用靜態局部變量替代全局變量,縮小作用域 |
| 類級共享計數/配置 | 用 static inline (C++17) 簡化定義 |
| 工具函數 | 放入命名空間 + static 或匿名命名空間,勿濫用類靜態方法 |
| 多線程環境 | 靜態局部變量初始化線程安全 (C++11),但讀寫需自行加鎖 |
| 跨 DLL 邊界 | 避免在 DLL 導出類中使用靜態數據成員(每個模塊有獨立拷貝) |
深入理解 static 的存儲期、鏈接屬性、作用域三大屬性差異,是寫出高質量、可維護 C++ 代碼的基石。