Effective C++閱讀記錄--前言(1)
Effective C++閱讀記錄--前言(1)
定義的本質
Object(物件)的定義給編譯器提供配置記憶體的地點說明。
function(函式)或者function template(函式模板)定義式為編譯器提供函式本體(function body)
物件陣列的初始化
C Array[10];
default constructor: 無需任何引數(argument)被呼叫,或者引數都有預設值。
想要定義一組包含類C的物件陣列,如果按照以上程式碼會定義包含十個C例項的陣列,而且會執行類C的預設建構函式(default constructor)。
但是當類物件沒有預設建構函式的話怎麼辦呢?
既然我們不能直接預設初始化物件,我們可以初始化指向該物件陣列的指標(其實就是把構造物件轉移到構造指向物件的指標)。
C *ptrArray[10]; //先初始化指標,實際上尚未分配物件
ptrArray[0] = new C(args); //再配置物件
疑問1:如果不使用預設建構函式,如何為每個陣列元素呼叫其他的建構函式?
拷貝建構函式(copy constructor)
本質上就是定義類如何以”by value“的方式傳遞和傳回物件。
函式傳參會呼叫到copy constructor。
只要編譯器決定產生中介的暫時性物件,就會需要copy constructor呼叫動作。
pass by value = 呼叫copy constructor。
初始化(initialization)與賦值(assignment)
初始化:物件的初始化發生在它初次獲取某個值的時候,總是呼叫constructor實現的。
賦值:發生在以初始化物件被賦予新值的時候。
雖然二者都會讓物件有新值,但是呼叫的函式是不一樣的。
string s1; //呼叫的是預設初始化函式
string s2("hello"); //直接初始化,呼叫普通建構函式
string s3 = s2; //呼叫拷貝建構函式
s1 = s3; //由operator=執行
初始化會檢驗傳遞的引數(argument)是否是合法的,但是賦值操作不會。
在assignment(賦值)運算子為一個新值配置記憶體之前,需要先釋放原來的值的記憶體。assignment認定引數是合法的,反而需要檢測有沒有自己賦給自己的情況,力保配置新記憶體前釋放舊記憶體。
但是constructor操作需要檢驗引數的正確性,確保member data(成員資料)都能被適當初始化。
Effecetive C++閱讀記錄--條款1
儘量以const和inline取代#define
const和inline是編譯器處理的工作,前處理器處理#define。因此儘量用編譯器取代前處理器。
#define ASPECT_RATIO 1.653
一般define定義巨集出現在標頭檔案中,使用的時候標頭檔案可能不是你自己寫的,但是ASPECT_RATION由於被前處理器全部處理成了1.653,並沒有進入符號表(symbol table)裡面。因此當你使用了這個巨集又出錯的時候,可能會對1.653這個數字很懵,你聯想不到是ASPECT_RATIO出了問題。原因:程式內所使用的名稱並未出現在符號表之中。
const double ASPECT_RATION = 1.653;
可以使用以上,定義一個常量。
當這個常量是給某個class專屬設計的時候,需要做兩樣工作。
①為了將這個常量的scope(生存空間)侷限在class之內,需要把他作為class的member。
②為了讓這個常量只有一份實體,需要讓它成為一個static member(也就是static關鍵字能避免一個變數被重複定義嗎)。