C/C++之常用关键字
Tips:
?1. 本人當初學習C/C++的記錄。
?2. 資源很多都是來自網上的,如有版權請及時告知!
?3. 可能會有些錯誤。如果看到,希望能指出,以此共勉!
??C及C++中變量的存儲方式有三種:自動、靜態、動態。在C++11中,額外增加了一種:線程存儲方式(關鍵字thread_local)。(C沒有)以下所謂的可見并不是指編程者可以直接使用,這里的可見是對編譯器/連接器來說的,它們在編譯鏈接時能夠發現其他文件中的變量。如果編程者要使用,還是必須顯示聲明。 C++標準使用翻譯單元表示編譯的單位,下面以文件為編譯單元來說的。
自動類型:程序執行到其所屬的函數或代碼塊時,才為其分配內存,直到其所屬的函數或者代碼塊結束,內存就被釋放了。
靜態類型:在整個程序運行過程中都存在。
動態類型:從new開始一直到delete或者程序結束。
線程存儲方式:與所屬的線程同生命周期。
auto關鍵字
??C中: auto關鍵字來源于C語言,唯一作用就是顯示指明所定義的局部變量為自動存儲類型(默認就是auto,常省略),而且auto只能用于修飾默認為自動存儲類型的變量(意味著,想定義auto int a = 0; 的全局變量是不可以的),因此幾乎沒有人使用它。
??C++中:但是從C++11開始,auto關鍵字有了全新的用法:自動判斷數據類型,原來的用法被視為非法。注意:C++11中,auto的變量必須在定義時初始化。
??如上例子中,變量a將自動判斷為int型,因為其被賦值為整型10。
??當然,auto關鍵字不僅僅是為了以上的簡單情況,對于上面的情況來說,auto顯得有點雞肋。對于復雜情況,例如標準模塊庫(STL),自動判斷才更有用。如下:
C++98中:
std::vector<double> scores;
std::vector<double> iterator pv = scores.begin();
C++11中:
std::vector<double> scores;
auto pv = scores.begin(); // 自動判斷,簡化代碼
register關鍵字
??C中: register關鍵字最初由C語言引入,它建議編譯器采用CPU的寄存器來存儲指定的自動類型變量,旨在提高變量的訪問速度。
??C++中:其用來告訴編譯器被其所修飾的局部變量使用頻繁,編譯器可以做特殊處理。
??C++11開始:其作用只是顯示指出定義的局部變量是自動存儲類型,而且只能修飾原本就是自動類型的變量。這與auto關鍵字原來的用法完全相同。保留的唯一原因就是代碼兼容。
mutable關鍵字
??主要用于C++中:該關鍵字跟constant(既C++中的const)是反義詞,用來指出即使結構體或者類為const類型,其成員只要被mutable修飾,值仍然可以被修改。該關鍵字只用在類中或者結構體中,用來修飾單個變量是不被允許的。
const關鍵字
??默認情況下,全局變量的可見性是所有文件,但是被const修飾的全局變量卻只在當前文件可見,和使用了static修飾一樣。這樣,在頭文件中定義的const變量,在被多個文件包含時,不會再出現重復包含。
extern關鍵字
??extern可以置于變量或者函數前,以標識變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。extern也可用來進行鏈接指定。也就是說extern有兩個作用:
extern “C” {
… // 代碼
}
extern變量
??extern用在變量聲明中常常有這樣一個作用,你在*.c文件中聲明了一個全局的變量,這個全局的變量如果要被其他模塊引用,使用前就要在使用的模塊中用extern來聲明。
??在定義變量的時候,這個extern可以被省略(定義時,默認均省略);在聲明變量的時候,這個extern必須添加在變量前。
定義和聲明的區別:定義要為變量分配內存空間;而聲明不需要為變量分配內存空間。定義只能一次,聲明可多次
extern函數
??由于函數的定義和聲明是有區別的,定義函數要有函數體,聲明函數沒有函數體(還有以分號結尾),所以函數定義和聲明時都可以將extern省略掉。關鍵字extern,僅僅是暗示這個函數可能在別的源文件里定義,沒有其它作用。即下述兩個函數聲明沒有區別:
extern int func(); 和int func(); // 等價
??上例中,main函數中調用了b.c中定義的函數,只要在第一次使用之前聲明了就可以。函數聲明,不管在哪里(跨文件),都可以省略extern關鍵字。
extern與#include “*.h”的區別
static關鍵字
static變量
??靜態變量屬于靜態存儲方式,其存儲空間為內存中的靜態數據區(在靜態存儲區內分配存儲單元),該區域中的數據在整個程序的運行期間一直占用這些存儲空間(在程序整個運行期間都不釋放),也可以認為是其內存地址不變,直到整個程序運行結束(相反,動態局部變量,屬于動態存儲類別,占動態存儲空間,函數調用結束后即釋放)。靜態變量雖在程序的整個執行過程中始終存在,但是在它作用域之外不能使用。
??另外,屬于靜態存儲方式的量不一定就是靜態變量。 例如:外部變量雖屬于靜態存儲方式,但不一定是靜態變量,必須由 static加以定義后才能成為靜態外部變量,或稱靜態全局變量。
靜態局部變量:
??函數內部的Static變量同自動變量(即未加 Static 聲明的局部變量)一樣,是某個特定函數的局部變量,即只能在定義該變量的函數內使用該變量,兩者作用域相同;兩者的不同在于:自動變量會隨著函數被調用和退出而存在和消失,而static類局部變量不會,它不管其所在的函數是否被調用,都將一直存在;不過,盡管該變量還繼續存在,但不能使用它。倘若再次調用定義它的函數時,它又可繼續使用,而且保存了前次被調用后留下的值。換言之,Static類型的內部變量是一種只能在某個特定函數中使用,但一直占據存儲空間的變量。
??函數體內如果在定義靜態變量的同時進行了初始化,則以后程序不再進行初始化操作(出現在函數內部的基本類型的靜態變量初始化語句只有在第一次調用才執行)。而對自動變量賦初值是在函數調用時進行,每調用一次函數重新給一次初值,相當于執行一次賦值語句。
??靜態局部變量的初始化表達式必須是一個常量或者常量表達式。即使局部靜態變量定義時沒有賦初值,系統會自動賦初值0(對數值型變量)或空字符(對字符變量);靜態變量的初始值為0。而對自動變量來說,如果不賦初值則它的值將是個不確定的值。
??當多次調用一個函數且要求在調用之間保留某些變量的值時,可考慮采用靜態局部變量。雖然用全局變量也可以達到上述目的,但全局變量有時會造成意外的副作用,因此仍以采用局部靜態變量為宜。
注:局部靜態變量占用內存時間較長,并且可讀性差,因此,除非必要,盡量避免使用局部靜態變量。
靜態全局變量
??全局變量(外部變量)的說明之前再冠以static 就構成了靜態的全局變量。全局變量本身就是靜態存儲方式,靜態全局變量當然也是靜態存儲方式。這兩者在存儲方式上并無不同。這兩者的區別在于:
非靜態全局變量的作用域是整個源程序,當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。
??靜態全局變量則限制了其作用域,即只在定義該變量的源文件內有效,在同一源程序的其它源文件中不能使用它。
靜態函數(又稱內部函數)
??C++和C一樣,不允許一個函數中定義另一個函數,所以函數默認都是靜態存儲的。函數的定義和聲明默認情況下是extern的。默認情況下,函數在程序執行的整個過程中都是存在的。其作用域為所有文件可見,這就要求多文件中不能定義同名函數。在函數的返回類型前加上關鍵字static,函數就被定義成為靜態函數。靜態函數只是在聲明他的文件當中可見,不能被其他文件所用。定義靜態函數的好處:
靜態函數必須在第一次調用之前就被聲明了,例如:頭文件中聲明沒有加static,只是在定義中加了static,是沒有用的!
類中的靜態變量和函數
靜態成員變量
??對于非靜態數據成員,每個類對象都有自己的拷貝。而靜態數據成員被當作是類的成員。無論這個類的對象被定義了多少個,靜態數據成員在程序中也只有一份拷貝,由該類型的所有對象共享訪問。也就是說,靜態數據成員是該類的所有對象所共有的。對該類的多個對象來說,靜態數據成員只分配一次內存,供所有對象共用。所以,靜態數據成員的值對每個對象都是一樣的,它的值可以更新- 靜態數據成員存儲在全局數據區。靜態數據成員定義時要分配空間,所以不能在類聲明中定義。
- 靜態數據成員和普通數據成員一樣遵從public、protected、private訪問規則。公共靜態數據成員可被類的外部訪問,保護或私有靜態數據成員只可被類的內部訪問
- 因為靜態數據成員在全局數據區分配內存,屬于本類的所有對象共享,所以,它不屬于特定的類對象,在沒有產生類對象時其作用域就可見,即在沒有產生類的實例時,我們就可以操作它
- 靜態數據成員初始化與一般數據成員初始化不同。靜態數據成員初始化必須在類體外進行,而前面不加static,以免與一般靜態變量或對象相混淆。格式為:
<數據類型><類名>::<靜態數據成員名>=<值> - 類的靜態數據成員有兩種訪問形式(訪問權限允許的話):
<類對象名>.<靜態數據成員名> 或 <類類型名>::<靜態數據成員名> - 靜態數據成員主要用在各個對象都有相同的某項屬性的時候。
- 同全局變量相比,使用靜態數據成員有兩個優勢:
- 靜態數據成員沒有進入程序的全局名字空間,因此不存在與程序中其它全局名字沖突的可能性
- 可以實現信息隱藏。靜態數據成員可以是private成員,而全局變量不能
靜態成員函數
??與靜態數據成員一樣,我們也可以創建一個靜態成員函數,它為類的全部服務而不是為某一個類的具體對象服務。靜態成員函數與靜態數據成員一樣,都是類的內部實現,屬于類定義的一部分。 普通的成員函數一般都隱含了一個this指針,this指針指向類的對象本身,因為普通成員函數總是具體的屬于某個類的具體對象的。通常情況下,this 是缺省的。如函數func()實際上是this->func()。 ??與普通函數相比,靜態成員函數由于不是與任何的對象相聯系,因此它不具有this指針。從這個意義上講,它無法訪問屬于類對象的非靜態數據成員,也無法訪問非靜態成員函數,它只能調用其余的靜態成員函數。關于靜態成員函數,可以總結為以下幾點:- 出現在類體外的函數定義不能指定關鍵字static,這一點尤為注意,很多時候在.h中定義類,在.cpp文件中寫具體實現,這是的靜態函數就不用static了。
- 靜態成員之間可以相互訪問,即:靜態成員函數訪問靜態數據成員和訪問靜態成員函數
- 非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員
- 靜態成員函數不能訪問非靜態成員函數和非靜態數據成員
- 由于沒有this指針的額外開銷,因此靜態成員函數與類的全局函數相比速度上會有少許的增長
- 不能將靜態成員函數定義為虛函數。
- 調用靜態成員函數,可以用成員訪問操作符(.)和(->)為一個類的對象或指向類對象的指針調用靜態成員函數,也可以直接使用如下格式:
<類名>::<靜態成員函數名>(<參數表>)
volatile關鍵字
??主要用于C語言,一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。例如: volatile int i=10; int j = i; ... int k = i; ??如果沒有 volatile關鍵字,由于編譯器發現兩次從i讀數據的代碼之間的代碼沒有對i進行過操作,它會自動把上次讀的數據放在k中。而不是重新從i里面讀;而加了volatile后,每次都會重新讀取i的值。 下面是volatile變量的幾個常用方式:一個參數既可以是const還可以是 volatile。例如:一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它
一個指針可以是volatile。一個例子是當一個中斷服務子程序修改一個指向一個buffer的指針時。
總結
以上是生活随笔為你收集整理的C/C++之常用关键字的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++之数据类型
- 下一篇: C/C++之函数