這篇文章對C++常見的一些關鍵字作一個總結,主要從關鍵字的基本概念、使用場景以及注意事項等方面敘述。
1. virtual
概念:virtual是定義虛函數的關鍵字。在使用virtual之前,C++對成員函數使用靜態聯編,而使用virtual,並且在調用時是通過指針或引用調用,C++則對成員函數進行動態聯編。virtual具有繼承性,即:只要基類定義了virtual,子類的該函數也就有virtual屬性。
使用場景:
- 定義類函數,使其成爲虛函數(友元函數、構造函數、static靜態函數不能用virtual關鍵字修飾,普通成員函數和析構函數可以用virtual關鍵字修飾);
- 虛繼承;
- 純虛函數,包含純虛函數的類爲抽象類,不能實例化;
2. inline
inline是爲了解決一些頻繁調用的小函數大量消耗棧空間的問題而引入的。一般函數代碼在10行之內,並且函數體內代碼簡單,不包含複雜的結構控制語句例如:while、switch,並且函數本身不是直接遞歸函數(自己調用自己)。
使用場景:
- 代碼段比較小,一般小於10行;
- 函數被頻繁調用;
注意事項:
- 遞歸調用的函數不應聲明爲inline函數;
- inline函數僅僅是一個對編譯器的建議,能否內聯要看編譯器;
- inline定義的類的內聯函數,函數代碼被放入符號表中,在使用時直接進行替換,省去了參數壓棧、棧幀開闢與回收、結果返回等,沒有了調用的開銷,效率高。比宏函數安全性高,會進行參數類型的檢查,不會出現語義上的問題;
- 類中定義的函數,自動轉換爲內聯函數;
- inline函數在運行時可以調試,而宏不可以;
缺點:
- inline函數的使用是空間換時間的方法。會導致代碼量增加;
- inline函數無法隨着函數庫升級而升級;
- 在調用inline函數時,要保證內聯函數的定義讓編譯器“看”到,也就是說內聯函數的定義要在頭文件中;
3. volatile
volatile關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器位置的因素更改,比如:操作系統、硬件或者其它線程等。由於訪問寄存器的速度要快過RAM,所以編譯器一般都會作減少存取RAM的優化。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優化,從而可以提供對特殊地址的穩定訪問。
三大特性:
- 易變性:是在彙編層面反映出來的,就是兩條語句,下一條語句不會直接使用上一條語句對應的volatile變量的寄存器內容,而是重新從內存中讀取;
- 不可優化性:volatile所修飾的變量,編譯器不會對其進行各種激進的優化;
- 順序性:C/C++ 對volatile變量和非volatile變量之間的操作,是可能被編譯器交換順序的(交換後無變化,在有些地方這樣處理就會出問題),對volatile變量間的操作,編譯器不會交換順序;
格式:類型 volatile 變量名;
舉個栗子:
int main()
{
int volatile a = 10;
.
.
int c = a;
return 0;
}
在上述代碼中,如果不加volatile,編譯器可能會進行優化,在進行 c = a 的時候,編譯器發現 a 爲改變,就會將寄存器裏存的a的值賦給 c,這對於非常容易改變變量的情況不適合,如果加了volatile,那麼每次需要訪問 a 的值都會從內存中讀取(因爲編譯器認爲此變量的值隨時都可能改變)。
使用場景:
- 多任務環境下各任務間共享的標誌應該加volatile;
- 中斷服務程序中修改的供其它程序檢測的變量需要加volatile;
- 存儲器映射的硬件寄存器通常也要加volatile說明,因爲每次對它的讀寫都可能有不同意義;
(待更新 decltype、mutable)
Reference :