斷言是很早之前就有的東西了,只需要引入cassert頭文件即可使用。往往assert被用於檢查不可能發生的行為,來確保開發者在調試階段盡早發現“不可能”事件真的發生了,如果真的發生了,那么就表示代碼的邏輯存在問題。最好的一點就是,斷言只在Debug中生效,因此對於Release版本是沒有效率上的影響的。
#include <iostream> #include <cassert> using namespace std; int main() { int i = 22; assert(i != 22); system("pause"); return 0; }
上面的代碼就表示,你確認在這里i一定不會等於22,如果事實上真的是22,那么程序就會無情地被abort,並報告出現問題的源文件和行號(使用了魔法常量__FILE__和__LINE__),有助於及時定位問題。
斷言有一個問題,就是一定會abort,強制整個程序退出而導致調試也無法繼續進行,就像上圖這樣,出現問題后,我們知道了出現問題的行號,但是我們需要手動在該行的上面設置斷點,重新開始調試才能夠檢查到發生問題時各個變量的狀態。而且,有時問題不是那么容易重現,於是就可能出現沒法重現錯誤再檢查狀態的問題。
所以,我們可以自己寫一個類似的宏來解決這個問題,我們希望在違反斷言時觸發斷點陷阱門中斷而不是調用abort,這樣,在違反斷言時程序會暫停下來,等待程序員來檢查當前的狀態有何異常。
下面是一個Visual C++中的實現。
#include <iostream> #include <cassert> using namespace std; #define _ASSERT(x) if (!(x)) __asm {int 3}; int main() { int i = 22; //assert(i != 22); _ASSERT(i != 22); system("pause"); return 0; }
上面定義了一個宏,名字當然可以自己取,實際上做的一件事就是檢查斷言,然后如果斷言結果為false(0),那么就調用內聯匯編指令int 3陷入調試中斷。
在2011年的C++標准中出現了靜態斷言(static_assert)的語法,所謂靜態斷言,就是在編譯時就能夠進行檢查的斷言,static_assert是C++的標准語法,不需要引用頭文件。靜態斷言的另一個好處是,可以自定義違反斷言時的編譯錯誤信息。
#include <iostream> using namespace std; int main() { const int i = 22; static_assert(i != 22, "i equals to 22"); system("pause"); return 0; }
這個代碼,將無法通過編譯,因為i的值違反了靜態斷言。
靜態斷言的限制是,斷言本身必須是常量表達式,如果這樣的i不是常量,靜態斷言是不符合語法的。


