1. 程式人生 > >C++第九章筆記

C++第九章筆記

和C一樣,C++為記憶體儲存資料方面提供了多種選擇,可以選擇資料保留在記憶體中的時間(生命域)以及程式的哪一部分可以訪問資料(作用域和連結)等。

單獨編譯

和C語言一樣,C++也允許甚至鼓勵程式設計師將元件函式放在獨立的檔案中。可以單獨編譯這些檔案然後將他們連結成可執行的程式。(IDE包含編譯器和連結器的原由吧)。

標頭檔案:包含結構宣告和使用這些結構的函式的原型

原始碼檔案:包含與結構有關的函式的程式碼

原始碼檔案:包含呼叫與結構相關的函式程式碼

不要將函式定義或變數宣告放在標頭檔案中,對於簡單的情況是可行的,但是如果存在重複包含標頭檔案的檔案,則會出現一個程式中將包含同一個函式的兩個定義,除非函式式內聯的,否則這將出錯。

標頭檔案經常包含的內容:

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

將結構宣告放在標頭檔案中是可以的,因為它們不建立變數,而只是在原始碼檔案中宣告結構變數時,告訴編譯器如何建立該結構變數。同樣,模板宣告不是將被編譯的程式碼,它們指示編譯器如何生成與原始碼中函式呼叫相匹配的函式定義。被宣告為const的資料和行內函數有特殊的連結屬性,因此可以放在標頭檔案。

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

在C++11中,有四種不同的方案來儲存資料,這些方案的區別在於資料保留在記憶體中的時間。

  • 自動儲存持續性(自動變數)
  • 靜態儲存持續性(靜態變數,全域性變數)
  • 執行緒儲存持續性(C++11,使用關鍵字thread_local)
  • 動態儲存持續性(動態記憶體)

作用域描述了名稱在檔案的多大範圍內可見。

作用域為區域性的變數只在定義它的程式碼塊中可用。程式碼塊是由花括號括起來的一系列語句。作用域為全域性(也叫做檔案作用域)的變數在定義位置到檔案結尾之間都可用。自動變數的作用域為區域性,靜態變數的作用域是全域性還是區域性取決於是如何定義的:

鏈結性描述了名稱如何在不同單元間共享:外部連結在檔案間共享,內部連結只能有一個檔案中的函式共享,自動變數沒有鏈結性,因為它們不能被共享。

mutable說明符指出,即使結構變數為const,其某個成員也可以被修改

struct data
{
char name[30];
mutable int accesses;
...
};

又是一個神器。。

new支援定位操作,

char s[100];
int *p = new(s) int[10];

便可以在s的空間中申明出一個10個元素的int陣列。神奇。

但是,因為畢竟不是在堆中開的記憶體,用delete會錯誤!

名稱空間

在C++中,名稱可以是變數、函式、結構、列舉、類以及類和結構的成員。當隨著專案的增大,名稱相互衝突的可能性增大。使用多個廠商的類庫時,可能導致名稱衝突。因此有了名稱空間。

傳統的C++名稱空間,

宣告區域是可以在其中宣告的區域比如函式外的全域性變數。

潛在作用域,變數在潛在作用域從宣告點開始,到其宣告區域結尾,因此潛在作用域比宣告區域小,這是由於變數必須定以後才能使用。

一個名稱空間不會和另外一個名稱空間衝突。

名稱空間可以是全域性也可以位於另外一個名稱空間中,但不能位於程式碼塊中,因此,預設情況下在名稱空間中宣告的名稱的連結性為外部。

名稱空間定義起來很簡單:

namespace Jill
{
char fetch(){...}
...
}

使用起來也簡單,

Jill::fetch();

為了程式設計簡單,於是有了using宣告和using編譯指令,

using Jill::fetch;

之後這個函式就可以正常使用了,

using namespace Jill;

之後,這個名稱空間裡的東西就可以正常使用了。

如果就著儘量節省的原則,前者可以節省更多的程式碼長度,因為沒有用到的函式等其他名稱空間的東西沒被宣告定義。

就著安全的原則,推薦使用第一種以避免多名稱空間中的名稱衝突。

名稱空間是可以巢狀的,不過也很簡單。

名稱空間可以未命名,因為名稱空間定義之後,裡面的東西就相當於全域性變數,但是未命名就限制了此空間內的東西只能在當前檔案使用。

名稱空間及其用途

  • 使用已命名的名稱空間中宣告的變數,而不是使用外部全域性變數
  • 使用已命名的名稱空間中宣告的變數,而不是使用靜態全域性變數
  • 僅將using作為一種將舊程式碼轉換為使用名稱空間的權宜之計
  • 不要在標頭檔案中使用using編譯指令,非要新增using的話,只少要保證include的正確順序
  • 匯入名稱空間時首選使用作用解析運算子或是using宣告而不是using編譯指令
  • 對於using宣告,,首選將其作用域設定為區域性而不是全域性

總之,名稱空間的引入是為了管理專案。


歡迎到微信裡去當吃瓜群眾