讓自己習慣C++、構(gòu)造/析構(gòu)/賦值運算

條款02 盡量以const,enum,inline替換#define
  • define nTemC 5并沒有使得nTemC被編譯器看見,有可能就沒有進入記號表內(nèi)。于是當使用此常量導(dǎo)致的編譯錯誤可能會提及5而不提及nTemC,這將使問題難以追蹤。并且由于預(yù)處理器盲目地將宏名稱替換為其對應(yīng)的東西而導(dǎo)致代碼產(chǎn)生冗余。const int nTemC = 5;則不會出現(xiàn)上述的問題。當在類中使用類的專屬常量的時候可以使用const來實現(xiàn),不能用#define實現(xiàn),因為#define不注重作用域,一旦宏被定義,它就在其后的編譯過程中有效(除非在某處被#undef)
  • 若要在頭文件內(nèi)定義一個常量字符串,必須寫const兩次
    const char* const pStrC = "1" \\第一個const是用于修飾指針所指字符串,加上這個const是很好的習慣,第二個const是修飾指針本身,定義于頭文件的變量必須是常量,所以第二個const是必須的
  • 定義于類內(nèi)static const變量最好在類外提供定義
class CTest
{
public:
    const static int CSValue0 = 1;  //類的專屬常量的聲明,附帶初始值。
    const static int CSValue1;      //類的專屬常量的聲明,無初始值
};

const static int CSValue0;          //類的專屬常量的定義。
const int CTest::CSValue1 = 1;      //類的專屬常量的定義。
  • 在class編譯期間需要一個class常量值也可以使用類內(nèi)枚舉。對一個const變量取地址是合法的,對一個枚舉值取地址是非法的,而取一個#define的地址通常也是不合法的

  • 優(yōu)秀的編譯器不會為整形const對象設(shè)定另外的存儲空間(除非創(chuàng)建一個指針或引用指向該對象),不過不夠優(yōu)秀的編譯器(包括vs2010)卻可能為const對象創(chuàng)建存儲空間。但是enum和#define都絕不會導(dǎo)致非必要的內(nèi)存分配

  • 宏看起來像函數(shù),但是不會招致函數(shù)調(diào)用帶來的額外開銷,使用inline則沒有相應(yīng)的問題

  • 有了const enum inline 我們對預(yù)處理器(特別是#define)的需求降低了,但是并非完全消除。#include仍然是必需品。#ifdef/#ifndef也扮演控制編譯的重要角色。

條款03 盡可能的使用const
  • 令函數(shù)返回一個常量值,往往可以降低因客戶錯誤而造成的意外,而不至于放棄安全性和高效性。
    const operator *(const CTest &Test1, const CTest &Test2); //可以有效防止比如: (Test0 * Test1) = Test2;
  • 將不需要被改變的量聲明為const的,有助于在判斷表達式中意外將==寫成=造成的錯誤,以及防止其被意外修改。
  • 將const作用于成員函數(shù)的目的是為了確認該成員函數(shù)可作用于const對象上。
  • 區(qū)分頂層const和底層const,頂層const表示const所修飾的變量本身是常量,而底層const一般作用于指針,表示指針所指對象是常量。
  • 將成員變量聲明為mutable的,則即使在常量成員函數(shù)中也能修改這個變量的值。
  • 當成員函數(shù)的常量版本和其非常量版本有著實質(zhì)的等價實現(xiàn)的時候,最好是在其非常量版本中調(diào)用常量的版本,反之則違背了常量成員函數(shù)不修改其成員的規(guī)則,可能會導(dǎo)致邏輯錯誤。
  • 不論將const用于何處,都能很好的向使用者說明當前const所修飾的符號將不會被更改。在開發(fā)或者調(diào)試的時候,是很節(jié)約review時間的

條款04 確定對象被使用前已經(jīng)被初始化
  • 讀取未初始化的值會導(dǎo)致不明確的行為。
  • C++對于定義在不同cpp中的全局變量的初始化順序沒有進行規(guī)定,所以一個cpp中的全局變量不要依靠另一個cpp中的全局變量進行初始化,否則可能會產(chǎn)生bug
  • 將全局變量局部static化。將每個全局變量搬到自己的專屬函數(shù)中,然后由用戶調(diào)用這些函數(shù)以獲取其需要的變量。C++保證,函數(shù)內(nèi)的局部static變量會在該函數(shù)調(diào)用期間,首次遇上該對象的定義式時被初始化(當此函數(shù)沒有被調(diào)用的時候就省去了此變量的構(gòu)造和析構(gòu))。
int& fun()  
{
    static int value = 10;
    return value;
}
  • 構(gòu)造函數(shù)最好使用成員初始化列表進行對其成員的初始化。

條款06 若不想使用編譯器自動生成的構(gòu)造函數(shù)、析構(gòu)函數(shù)等函數(shù),則明確的拒絕
  • 將對應(yīng)函數(shù)聲明為private且不進行定義,防止外部函數(shù)、友元函數(shù)、成員函數(shù)進行調(diào)用

條款07 為多態(tài)基類聲明virtual析構(gòu)函數(shù)
  • 基類的析構(gòu)函數(shù)不定義為虛函數(shù),則不要對其進行派生,否則由于基類的指針或引用可以指向派生類的對象,則在刪除基類對象的時候可能會出錯,導(dǎo)致破壞數(shù)據(jù)結(jié)構(gòu)。
  • 不要為普通的類聲明一個虛析構(gòu)函數(shù)。這是因為C++為了實現(xiàn)虛函數(shù),會建立一個由函數(shù)指針構(gòu)成的數(shù)組,稱為虛函數(shù)表,導(dǎo)致類的對象必須攜帶額外信息來決定運行期間哪個虛函數(shù)會被調(diào)用,這個額外信息通常由一個指針組成,此指針指向虛函數(shù)表。當為類聲明有虛函數(shù)的時候,會使得類的對象占用更多的內(nèi)存,在32位程序下,會多出4字節(jié),在64位程序下會多出8字節(jié)

條款08 別讓異常逃離析構(gòu)函數(shù)
  • 析構(gòu)函數(shù)絕對不要吐出異常,如果一個被析構(gòu)函數(shù)調(diào)用的函數(shù)有可能拋出異常,析構(gòu)函數(shù)應(yīng)該捕獲任何異常,然后吞下他們或者結(jié)束程序
  • 如果客戶需要對某個操作函數(shù)運行期間拋出的異常做出反應(yīng),那么類應(yīng)該提供一個普通函數(shù)而非在析構(gòu)函數(shù)中執(zhí)行該操作

條款09 絕對不要在構(gòu)造和析構(gòu)過程中調(diào)用虛函數(shù)
  • 如下代碼,當構(gòu)造CChild類的成員的時候,其父類的成員首先被構(gòu)造,則先調(diào)用其父類的構(gòu)造函數(shù),其父類構(gòu)造函數(shù)中調(diào)用了一個虛函數(shù),此時并不會發(fā)生動態(tài)綁定,這里調(diào)用的虛函數(shù)是父類的版本。對象析構(gòu)的時候也是如此。
class CFather
{
public:
    CFather()    {Fun();}
    virtual void Fun(){printf("Father virtual ");}
};
class CChild : public CFather
{
public:
    CChild()    {Fun();}
    virtual void Fun(){printf("Child virtual ");}
};
CChild child;
//輸出Father virtual Child virtual 而不是 Child virtual Child virtual 


條款10 令operator=返回一個reference to *this
  • 是為了能進行連續(xù)復(fù)制,以符合類似于內(nèi)置類型的操作

條款11 在operator=中處理自我賦值


條款12 復(fù)制對象時勿忘其每一個成分
  • 復(fù)制所有本類的成員變量,調(diào)用其基類的適當?shù)目截惡瘮?shù)
  • 通常拷貝構(gòu)造函數(shù)與拷貝賦值運算符所做的工作很接近,但是最好不要讓其中一個調(diào)用另一個,應(yīng)該定義一個新的函數(shù),供這兩個函數(shù)調(diào)用。
  • 令拷貝賦值運算符調(diào)用拷貝構(gòu)造函數(shù)是不合理的,因為這就像試圖構(gòu)造一個已經(jīng)存在的對象,這是很荒謬的。
  • 令拷貝構(gòu)造函數(shù)調(diào)用拷貝賦值運算符也是不合理的,因為拷貝構(gòu)造函數(shù)是用來初始化新對象,而拷貝賦值運算符只實施在已初始化的對象上,所以從邏輯上講也是不合理的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • “爺爺,爺爺,天上好多的星星,好漂亮啊!我好像碰碰他們,和他們交朋友” “你想要和星星交朋友那你要趕緊長大...
    月明天清閱讀 632評論 0 1
  • 一生這么長,一生這么短,想做的事太多了,一個一個的來吧,沒有一生的志向,也是一種志向呢?
    若余fish閱讀 99評論 0 0
  • 在寫這篇文章的時候,我的心情依然是怒不可遏。其實,真的是很小很小的事情,但總能使我暴跳如雷。 同事喜歡跟我借書,而...
    閆小凡閱讀 380評論 0 1
  • 寫作之初,你往往會覺得自己“抓不到主題思想”,難以下筆。甚至靠寫作為生的專業(yè)作家也常常會碰到這個困難。在這個時候半...
    晏櫻閱讀 1,082評論 2 3