在 C++ 中定義常數,主要有兩種做法:傳統的前處理指令 #define 與 C++ 關鍵字 const。雖然兩者都能達到「定義常數」的目的,但底層機制、型別安全與除錯體驗截然不同。現代 C++ 強烈建議使用 const(或 C++11 的 constexpr),本文詳細比較兩者差異。
#define PI 3.1415926 // 無分號結尾
#include <iostream>
#define PI 3.1415926
double Area(int r) { return PI * r * r; }
int main() { std::cout << Area(2) << std::endl; }
const double PI = 3.1415926; // 需分號,指定型別
#include <iostream>
const double PI = 3.1415926;
double Area(int r) { return PI * r * r; }
int main() { std::cout << Area(2) << std::endl; }
| 特性 | #define | const |
|---|---|---|
| 型別安全 | 無(純文字替換) | 完整型別檢查 |
| 作用域 | 全域(檔案範圍) | 遵循區塊/類別/命名空間作用域 |
| 除錯可見性 | 除錯器看不到符號 | 完整支援監看與中斷點 |
| 記憶體佔用 | 不佔用(直接內嵌) | 一般有位址(最佳化時可能內嵌) |
| 指標/參考操作 | 不可取址 | 可取址、可綁定參考 |
| 邊際效應風險 | 高(如 #define SQR(x) x*x) | 無 |
const double PI 明確指定型別,避免隱性轉換錯誤#define 只能看替換後結果C# 保留 #define 僅用於條件編譯(如 #if DEBUG),不支援定義數值常數。數值常數請使用 const 或 readonly。另可搭配 [Conditional("SYMBOL")] 屬性實現方法層級條件編譯(僅限 void 方法)。
const T name = value;(C++11 起可用 constexpr)#if、#ifdef)使用 #defineinline 函數或 constexpr 函數MAX_BUFFER_SIZE)