C++內存模型

一、存儲持續性函數

C++使用四種不一樣方案來存儲數據,它們的區別在於數據在內存中保留的時間,也叫作存儲持續性spa

(1)自動存儲持續性線程

  在函數定義中聲明的變量,包括函數參數。翻譯

(2)靜態存儲持續性code

  在函數定義外和使用關鍵字static定義的變量。它們在程序整個運行過程當中都存在。blog

(3)線程存儲持續性內存

  在C++11中,若是使用關鍵字thread_local聲明變量,則變量生命期和所屬線程同樣長。ci

(4)動態存儲持續性作用域

  使用new運算符分配內存的數據。編譯器

二、做用域和連接性

做用域描述了名稱在文件的多大範圍內可見。包括函數定義或者代碼塊內可見、當前文件內可見和整個程序可見。連接性描述了名稱如何在不一樣單元間共享。連接性爲外部的名稱可在文件間共享,連接性爲內部的名稱只能在當前文件中共享。自動變量的名稱沒有連接性,由於它們不能共享。做用域和連接性的意思同樣。

三、靜態存儲持續性變量的做用域和連接性

靜態存儲持續性地變量在程序運行過程當中在內存中都存在,靜態變量默認被初始化爲0,包括三種做用域和連接性

(1)外部連接性(做用域爲整個程序)

在函數或者代碼塊外面聲明的變量,也稱爲外部變量

(2)內部連接性(做用域爲當前文件)

在函數或者代碼塊外面聲明,而且使用static限定符的變量

(3)無連接性(做用域爲當前函數或者代碼塊)

在函數或者代碼塊內部聲明,而且使用static限定符的變量

四、單定義規則

同一個變量,只能有一次定義和初始化。C++提供了兩種變量聲明,一種爲定義聲明(defining declaration),簡稱定義,它爲變量分配存儲空間;一種爲引用聲明(referencing declaration),簡稱聲明,它不給變量分配存儲空間。引用聲明使用關鍵字extern。外部連接性變量能夠在頭文件中進行聲明,在源文件中進行定義和初始化,其餘文件只要引用該頭文件便可以訪問該變量。內部連接性變量通常在源文件中定義變量,可是在頭文件中定義變量也不影響,由於它的做用域爲當前文件,若是兩個源文件都引用該頭文件,那麼在兩個文件中都將分別定義一個變量,分配兩塊內存。

五、const外部變量

默認狀況下全局變量的連接性爲外部的,加上const修飾符後,連接性爲內部的。若是但願const修飾的常量連接性爲外部的,則使用extern來修飾,例如extern const int i = 10。和外部變量不一樣,外部常量定義和聲明必須都加extern修飾符。

六、函數和連接性

函數的存儲持續性爲靜態的,連接性默認爲外部的。能夠在源文件中定義函數,在頭文件中使用extern聲明函數,固然extern能夠省略。須要在函數定義和聲明添加static關鍵字將函數的連接性變爲內部的。非內聯函數默認也要知足單定義規則,內聯函數不受這一約束。

七、語言的連接性

連接程序要求每一個函數都有不一樣的符號名。在C語言中,一個名稱只對應一個函數,很容易實現。通常C語言編譯器可能將fun這樣的函數翻譯爲_fun。這種方法被稱爲C語言連接性。C++語言由於重載的使用,一個名稱能夠對應多個函數。C++編譯器須要執行名稱矯正或者名稱修飾,爲重載函數生成不一樣的符號名。例如,可能將fun(int)轉換爲_fun_i,將fun(double,double)轉換爲_fun_d_d,這種方法被稱爲C++語言連接性。若是在C++語言中使用C語言編譯的庫,則由於語言連接性不一樣,連接器沒法尋找正確的函數符號,須要指定連接器按照C語言連接性去尋找函數符號。例如:

extern "C" void fun(int);

通常若是編譯的C庫不只供C程序調用,也供C++程序使用,能夠在C庫頭文件中添加以下代碼

#ifdef __cplusplus       //若是採用了C++,以下代碼使用C編譯器
    extern "C" {            //在C語言中添加extern "C"會報錯,由於這是C++語言的語法
#endif
/*C語言頭文件*/
#ifdef __cplusplus      //結束使用C編譯器
    }
#endif   
相關文章
相關標籤/搜索