int fac(int n) {
static int f = 1; // 靜態局部變量
f = f * n;
return f;
}
// 呼叫 fac(1)..fac(5) 輸出 1,2,6,24,120 看似正常
// 但再次呼叫 fac(3) → 360(錯誤!狀態已汙染)
將緊密耦合的三要素——迭代變量 i、累積變量 f、運算邏輯 f*=i——強行拆分:
i 留在呼叫端迴圈f 藏在 static 內部這是功能性閹割:原本有機整體被割裂,函數變成「一次性用品」,嚴重違反低耦合、高內聚原則。函數應無狀態、可重入、僅依賴參數——這才是「本分」。
// 遞歸版
int fac(int n) { return n <= 1 ? 1 : n * fac(n - 1); }
// 迭代版(推薦)
int fac(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) result *= i;
return result;
}
const char* month(unsigned m) {
static const char* const name[12] = {
"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"
};
return name[m - 1]; // 唯讀,無副作用,線程安全(C++11 起初始化原子)
}
特徵:
const)| 場景 | 是否適合 | 理由 |
|---|---|---|
| 可變狀態累積(計數器、快取) | ❌ | 破壞重入性、線程不安全、測試困難 |
| 單例模式 | ⚠️ | C++11 推薦 static T& instance() { static T inst; return inst; }(Meyer 單例) |
| 大型唯讀查找表/常量表 | ✅ | 避免重複構造,唯讀天然線程安全 |
| 函數內部一次性初始化 | ✅ | 配合 std::call_once 或 C++11 魔法靜態 |
static 局部變量是把雙刃劍。默認拒絕可變 static local,除非是不可變資料或受控初始化。函數應像數學函數:同輸入必得同輸出,無副作用,無隱藏狀態——這是可維護、可測試、可併發代碼的基石。