Effective C++學習筆記(一)


條款一 C++是一個語言聯邦

建議

  • c++是有兄弟的:C,Object-Oriented c++(c with class),template c++,STL
  • c++高效編程守則視狀況而變化,取決於你使用c++的哪一部分。

條款二 盡量使用const, enum, inline代替define。

  • 寧可編譯器替換預處理器比較好。因為define不被視為語言的一部分。

    define NUM 3
    

    define在預處理器中已經替換成為具體的值,當編譯遇到一個常量錯誤的時候,你可能會感到困惑,因為錯誤信息提到的可能是3,而不是NUM。
    而且當NUM的定義不是你所設計的時候,你可能會因為去查找3這個值所引發的錯誤到底是為什么而頭大!這個問題也可能出現在記號調試器(symbolic debugger)中,原因相同:你所使用的名稱可能並未進入記號表(symbol table)
    另一個原因是:const可以成為作用域中的一個成員,define並不能行,且不能提供任何封裝性。
    還有一個原因是#define的函數

    #define MAX(a,b) func((a)>(b)?(a):(b))
    int a=5,b=0;
    MAX(++a,b);		     //a被累加二次
    MAX(++a,b+10);	    //a被累加一次
    

    在這里,調用f之前,a的遞增次數不定!
    建議用內聯模板

建議

  • 對於單純常量,最好以const對象或者enum替換#define
  • 對於形似函數的宏,最好改用inline函數替換

條款三 盡量使用const。

  • const在常量中的運用。

    char greet[] = "hello";
    const char* p = greet; //const data,non-const pointer;
    char* const p = greet; //non-const data,const pointer;
    const char* const p = greet; //const data,const pointer;
    

    迭代器中:

    vector<int>vec;
    const vector<int>::iterator iter = vec.begin();
    *iter = 10;		 //沒問題,改變iter所指的實體;
    ++iter;          //錯誤!iter是const
    
    //其實看過const_iterator的實現就知道,他就是對實體對象的一個const
    vector<int>::const_iterator citer = vec.begin();
    *citer = 10;		 //錯誤!*citer是const;
    ++citer;            //沒問題!改變citer
    
  • const在函數中的運用

    const Rational operator*(const Rational &lhs);

    避免用戶XJBY。

  • const成員函數

    第一,他們使得class接口比較容易理解,可以知道哪個函數可以改動對象內容,哪個函數不行。
    第二,他們使得“操作const對象”成為可能。

  • 編譯器強制實施bitwise constness,但你編寫程序時應該使用概念上的常量性

  • 當const和non-const成員函數有着實質等價的實現時,令non-const版本調用const版本可避免代碼重復。但是要做好類型轉換,否則會出現自己調用自己的現象。

    const char& operator[] (int position) const
    {
        return m_text[position];
    }
    
    /*  返回類型是個reference to char,不是char  */
    char &operator[](int position)
    {
        return m_text[position];
        /*調用const operator[]*/
        /*
        return const_cast<cahr&>(const TextBlock&)(*this)[position]);
        */
    }
    

建議

  • const真的是一個磨人的小妖精

條款四 確定對象在使用前已經初始化。

  • 為內置型對象進行手工初始化,因為C++不保證初始化它們。

  • 構造函數最好使用成員初始化列表(member initialization list),而不要在構造函數本體內使用賦值操作(assignment)。初值列列出的成員變量,其排列次序應該和它們在class中的聲明次序相同。
    C++規定,對象的成員變量的初始化動作發生在進入構造函數本體之前。構造函數體內的“=”叫做“賦值”,初始化發生的時間更早,發生於這些成員的default構造函數被自動調用之時。
    賦值構造的實質是:先設定初值,再為它們賦予新值。
    成員列表初始化:避免上述問題,同時避免調用copy構造函數,高效很多

  • 為免除“跨編譯單元之初始化次序”問題,請以local static對象替換non-local static對象。(不是很明白)

建議

  • 記得初始化!
  • 可以使用初始化列表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM