利用預處理器開關,編譯期完全移除調試代碼,零運行開銷。
#define DEBUG // 發布版註釋掉或 #undef DEBUG
#ifdef DEBUG
// 調試代碼:日志、檢查、統計...
std::cout << "Debug: x = " << x << std::endl;
#endif
優點:發布版無痕;缺點:需重新編譯切換。
無需重新編譯,通過命令行參數動態啟用/禁用調試。
bool debug = false;
int main(int argc, char* argv[]) {
for (int i = 0; i < argc; ++i)
if (std::string(argv[i]) == "--debug=on")
debug = true;
while (running) {
if (debug) {
// 調試代碼
}
// 正常邏輯
}
}
適用於服務程序、長時間運行進程、CI/CD 環境動態排查。
利用預處理器 # 運算符,自動將變量名轉為字符串,配合流輸出。
#define PR(x) std::cout << #x << " = " << (x) << '\n'
int value = 42;
PR(value); // 輸出: value = 42
PR(value * 2 + 1); // 輸出: value * 2 + 1 = 85
快速檢查變量值與表達式結果,無需手寫字符串字面量。
<cassert>ed 提供運行期契約檢查,失敗時輸出文件、行號、表達式並終止程序 (或觸發調試器)。
#include
int main() {
int i = 100;
assert(i != 100); // 失敗:Assertion failed: i != 100, file main.cpp, line 10
// 發布版禁用斷言:在 #include **之前** 定義 NDEBUG
// #define NDEBUG
// #include
}
關鍵:NDEBUG 必須在包含 <cassert>ed **之前** 定義,否則斷言代碼仍會編譯進去。
| 技巧 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| 條件編譯 | 開發期大量調試輸出 | 發布版零開銷 | 需重新編譯切換 |
| 運行期開關 | 生產環境排查、服務程序 | 無需重啟/重編譯 | 發布版保留代碼(極小開銷) |
| 字符串化宏 | 快速打印變量/表達式 | 代碼極少、自動同步名稱 | 宏副作用風險(參數求值多次) |
| assert | 前置/後置條件、不變式檢查 | 標準化、自動定位、可全局禁用 | 釋放版失效、不適用可恢復錯誤 |