在C/C++ 編程中,volatile與const關鍵字一貫容易讓人困惑,固然,新手可能歷來不用,可是 在高質量和穩健的程序中,這兩個關鍵字 是至關重要的。程序員
相比const,volatile關鍵字的發展(變化)較少,從C到C++的演變中,一直保持着 它的語義,所以,咱們先從volatile來了解下,這兩個關鍵字面試
volatile 的英文 釋義是 容易 揮發的,編程
做爲 關鍵字,能夠 記憶爲 它修飾的 變量 是 不穩定的,可能被其餘地方的某些方式改變,所以爲了 獲取正確的值,編譯器 不應對其作優化,好比爲了 獲取較快的 讀取速度,將它 放入寄存器中等,而是每次都要從它所在的內存中 讀取。安全
BS在 書中 對 volatile 的定義是:多線程
A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.ide
volatile修飾符 意在暗示 編譯器,該被修飾的對象 經過該語言未指定的方式改變他的值,所以,積極的優化都應該被消除。函數
未指定的方式 ,好比 操做系統,硬件或者其餘線程等。學習
遇到volatile修飾的變量,編譯器對訪問該變量的代碼 再也不進行優化,從而能夠提供對特殊地質的穩定訪問。優化
穩定的訪問的方式 是 ,系統老是從新從該 變量的 內存中讀取數據,即便 它 前面的 指令 剛剛 從該處 讀取過數據。spa
咱們可使用 volatile修飾 指針,好比
volatile char * myVolatileStr; char *volatile strVolatilePtr;
volatile 修飾 char* 和 *char 是 有較大區別的,和const修飾同樣,volatile能夠將其修飾的 內存區域 聲明爲 易揮發的,也能夠將 指針變量自己聲明爲 易揮發的。一般,有如下注意點:
注意:(1) 能夠把一個非volatile int 賦給 volatile int,可是不能把非volatile對象賦給一個volatile對象。
(2) 除了基本類型外,對用戶定義類型也能夠用volatile類型進行修飾。
(3) C++中一個有volatile標識符的類只能訪問它接口的子集,一個由類的實現者控制的子集。用戶只能用const_cast來得到對類型接口的徹底訪問。此外,volatile向const同樣會從類傳遞到它的成員。
在 多線程 中,有些變量是要用volatile關鍵字聲明的。當兩個線程都要用到某一個變量且該變量的值會被改變時,應該用volatile聲明,該關鍵字的做用是防止優化編譯器把變量從內存裝入CPU寄存器中。若是變量被裝入寄存器,那麼兩個線程有可能一個使用內存中的變量,一個使用寄存器中的變量,這會形成程序的錯誤執行。volatile的意思是讓編譯器每次操做該變量時必定要從內存中真正取出,而不是使用已經存在寄存器中的值,
下面,來對比學習 下 const,
在C++中,老手們建議 咱們 儘量的 多使用 const,可是 爲啥呢?若是 面試官 問起,你就說,爲了程序的穩健性,可是 這和問 鍛鍊身體爲啥呢,保衛祖國 ,沒什麼 區別。
const 理論上 是 constant的簡寫,constant的英文釋義是 不變的;恆定的;常常的。可是 不少大神將它理解成了 只讀的,readonly,甚至以爲 要把這個關鍵詞 替換成readonly。這在gun編譯器中也是這麼 提錯的,頗有意思。
和volatile同樣,const也是對編譯器的約束(廢話),它明確的告訴 編譯器,const修飾的變量 是 不變的,若是出現了 其餘地方的對其修飾值的改變,應該在編譯期間就報錯。這樣能大大提升程序的健壯性,固然,對於程序員,在編譯期間就發現錯誤本就是極好的。
這是 最基本的用法,如
const int i = 5; int const i = 4;
const char* str; char * const str; char const* str; const char* const str; const char const* str;
void function(constintVar);//傳遞過來的參數在函數內不能夠改變(無心義,由於Var自己就是形參)
void function(constchar*Var);//參數指針所指內容爲常量不可變
void function(char*constVar);//參數指針自己爲常量不可變(也無心義, 由於char* Var也是形參)
void function(constClass&Var);//引用參數在函數內不能夠改變
void function(const TYPE&Var);//引用參數在函數內爲常量不可變
class AAA { void func1(); void func2()const; } const AAA aObj; aObj.func1();//× aObj.func2();//正確 const AAA* aObj =new AAA(); aObj->func1();// × aObj->func2();//正確
class A { … constint nValue; //成員常量不能被修改 … A(int x): nValue(x){};//只能在初始化列表中賦值 }
class A { … void function()const;//常成員函數, 它不改變對象的成員變量. 也不能調用類中任何非const成員函數。 }