1. 程式人生 > >C++基礎學習之記憶體模型與名稱空間(5)

C++基礎學習之記憶體模型與名稱空間(5)

單獨編譯

將程式分為三個部分:

  • 標頭檔案:包含結構宣告和使用這些結構的函式的原型。
  • 原始碼檔案:包含與結構有關的函式的程式碼。
  • 原始碼檔案:包含呼叫與結構相關的函式的程式碼。

一般儘量避免將函式定義或變數宣告放到標頭檔案中,防止出現重複定義的問題。
標頭檔案經常包含的內容:

  • 函式原型
  • 使用 #define或const定義的符號常量
  • 結構宣告
  • 類宣告
  • 模板宣告
  • 行內函數

標頭檔案格式:

#ifndef COORDIN_H_
#define COORDIN_H_
// place include file contents here
#endif

儲存持續性,作用域和連結性

C++中四種儲存資料的方案:

  • 自動儲存持續性:在函式定義中宣告的變數(包括函式引數)的儲存持續性為自動的。它們在程式開始執行其所屬的函式或程式碼塊時被建立,在執行完函式或程式碼塊時,它們使用的記憶體被釋放。C++有兩種儲存持續性為自動的變數。
  • 靜態儲存持續性:在函式定義外定義的變數和使用關鍵字static定義的變數的儲存持續性都為靜態。它們在程式整個執行的過程中都存在。C++有三種儲存持續性為靜態的變數。
  • 執行緒儲存持續性(C++11):當前,多核處理器很常見,這些CPU可同時處理多個執行任務。這讓程式能夠將計算放在可並行處理的不同執行緒中。如果變數是使用關鍵字thread_local宣告的,則其生命週期與所屬的執行緒一樣長。
  • 動態儲存持續性:用new運算子分配的記憶體將一直存在,知道使用delete運算子將其釋放或程式結束為止。這種記憶體的儲存持續性為動態,有時被稱為自由儲存或堆。

自動儲存持續性變數

在一個函式中定義了變數則這個變數只在這個函式中使用,如果在一個函式中定義了變數teledei和websight,而在函式中的一個程式碼塊中又定義了teledei,那麼在執行到這個程式碼塊時,之前的teledei將被隱藏,在這個程式碼塊中將使用新定義的teledei,也就是說不會對原來的teledei造成影響,程式碼塊結束後新定義的teledei被釋放,原來的teledei重新可用。而且在程式碼塊中是可以直接使用websight的。
自動變數使用棧來儲存,所以執行完之後恢復棧頂位置即可釋放變數所佔記憶體。

靜態持續變數

C++為靜態儲存持續性變數提供了3種連結性:外部連結性(可在其它檔案中訪問)、內部連結性(只能在當前檔案中訪問)和無連結性(只能在當前函式或程式碼塊中訪問)。這3種連結性都在整個程式執行期間存在,與自動變數相比,它們的壽命更長。
要想建立連結性為外部的靜態持續變數,必須在程式碼塊的外面宣告它;要建立連結性為內部的靜態持續變數,必須在程式碼塊的外面宣告它,並使用static限定符;要建立沒有連結性的靜態持續變數,必須在程式碼塊內宣告它,並使用static限定符。

...
int global = 1000;
static int one_file = 50;
int main()
{
...
}
void funct1(int n)
{
	static int count = 0;
	int llama = 0;
	...
}

上面程式中定義的global、one_file、count在整個程式執行其間都存在。在funct1()中宣告的變數count的作用域為區域性,沒有連結性,這意味著只能在funct1()函式中使用它。但是count在funct1沒有執行時,count也留在記憶體中。而global和one_file的作用域為整個檔案。也就是說定義在函式外部的不加static關鍵字也是靜態變數,而在函式內想定義靜態變數必須使用關鍵字static。
外部變數可以作為全域性變數,可能會在其它檔案中用到,所以其它檔案用到的時候必須對這個變數進行引用宣告,宣告方式如下:

// file01.cpp
extern int cats = 20;	// definition because of initialization
int dogs = 22;	//definition
int fleas;	//definition
...
// file02.cpp
// use cats and dogs from file01.cpp
extern int cats;	//not definition because they use
extern int dogs;	//extern and have no initialization
...
// file98.cpp
// use cats, dogs, and fleas from file01.cpp
extern int cats;
extern int dogs;
extern int fleas;
...

另外檔案中已經extern聲明瞭變數後,這個檔案中的函式如果重新定義同名變數則會隱藏這個全域性變數,此時如果再想使用全域性變數可以加::para_name來使用它。
如果在兩個檔案中都定義同一個外部變數會產生錯誤:

// file1
int errors = 20;
// file2
int errors = 5;

這種情況可以在file2中的定義之前加上static關鍵字表明這個變數的連結性為內部,這樣就會隱藏外部變數而使用新定義的變數。
另外對於const關鍵字,它的連結屬性和static一樣,因此想要在其它檔案中使用這樣的變數,需要在const前再加一個extrern關鍵字來覆蓋掉const的內部連結屬性。
此外,extern和static也可以用在函式定義之前。

使用new運算子進行初始化

下面的幾段程式碼演示了對標量、陣列、等進行初始化:

int * pi = new int (6);	// *pi set to 6
double * pd = new double (99.99)	// *pd set to 99.99

struct where {double x; double y; double z;};
where * one = new where {2.5, 5.3, 7.2};
int * ar = new int [4] {2, 4, 6, 7};

int * pi = new int {6};	// *pi set to 6
double * pd = new double {99.99};	// *pd set to 99.99

名稱空間

一般在大型專案中名稱空間對於專案的使用更加友好,所以在參與大型專案的時候要再仔細看這部分的內容。