更多內容請看C/C++技術專題專題,或 volatile要害字 volatile是c/c++中一個鮮為人知的要害字,該要害字告訴編譯器不要持有變量的臨時拷貝,它可以適用于基礎類型 如:int,char,long......也適用于C的結構和C++的類。當對結構或者類對象使用volatile修飾的時候,結構或者 類的所有成員都會被視為volatile. 使用volatile并不會否定對CRITICAL_SECTION,Mutex,Event等同步對象的需要 例如: int i; i = i + 3; 無論如何,總是會有一小段時間,i會被放在一個寄存器中,因為算術運算只能在寄存器中進行。一般來說,volatitle 要害字適用于行與行之間,而不是放在行內?! ∥覀兿葋韺崿F一個簡單的函數,來觀察一下由編譯器產生出來的匯編代碼中的不足之處,并觀察volatile要害字如何修正 這個不足之處。在這個函數體內存在一個busy loop(所謂busy loop也叫做busy waits,是一種高度浪費CPU時間的循環方法) void getKey(char* pch) { while (*pch == 0) ; } 當你在VC開發環境中將最優化選項都關閉之后,編譯這個程序,將獲得以下結果(匯編代碼)
; while (*pch == 0) $L27 ; Load the address stored in pch mov eax, DWord PTR _pch$[ebp] ; Load the character into the EAX register movsx eax, BYTE PTR [eax] ; Compare the value to zero test eax, eax ; If not zero, exit loop jne $L28 ; jmp $L27 $L28 ;} 這段沒有優化的代碼不斷的載入適當的地址,載入地址中的內容,測試結果。效率相當的低,但是結果非常準確 現在我們再來看看將編譯器的所有最優化選項開關都打開以后,重新編譯程序,生成的匯編代碼,和上面的代碼
比較一下有什么不同
;{ ; Load the address stored in pch mov eax, DWORD PTR _pch$[esp-4]
; Load the character into the AL register movsx al, BYTE PTR [eax] ; while (*pch == 0) ; Compare the value in the AL register to zero test al, al ; If still zero, try again je SHORT $L84 ; ;}
寫一次getKey函數,并把參數pch聲明為volatile,代碼如下: void getKey(volatile char* pch) { while (*pch == 0) ; } 這次的修改對于非最優化的版本沒有任何影響,下面請看最優化后的結果: ;{ ; Load the address stored in pch mov eax, DWORD PTR _pch$[esp-4] ; while (*pch == 0) $L84: ; Directly compare the value to zero cmp BYTE PTR [eax], 0 ; If still zero, try again je SHORT $L84 ; ;} 這次的修改結果比較完美,地址不會改變,所以地址聲明被移動到循環之外。地址內容是volatile,所以每次循環 之中它不斷的被重新檢查?! “岩粋€const volatile變量作為參數傳遞給函數是合法的。如此的聲明意味著函數不能改變變量的值,但是變量的 值卻可以被另一個線程在任何時間改變掉?! XPlicit要害字 我們在編寫應用程序的時候explicit要害字基本上是很少使用,它的作用是"禁止單參數構造函數"被用于自動型別轉換,其中比較典型的例子就是容器類型,在這種類型的構造函數中你可以將初始長度作為參數傳遞給構造函數.
例如: 你可以聲明這樣一個構造函數
class Array { public: explicit Array(int size); ...... }; 在這里explicit要害字起著至關重要的作用,假如沒有這個要害字的話,這個構造函數有能力將int轉換成Array.一旦這種情況發生,你可以給Array支派一個整數值而不會引起任何的問題,比如: