C++基礎知識面試必備、複習細節 (4){Effective c++}

C++基礎知識面試必備、複習細節 (4) {Effective c++}

儘量以const,enum,inline替換#define
const double Ratio=1.65; //用該方式定義常量
#define Ratio 1.65;   //儘量不要以define方式定義常量

//在類中,也可以用enum替換define
class GamePlayer{
    enum{NumTurns=5};  //NumTurns就成爲5的一個記號
    int scores[NumTurns];
}

//採用inline函數方式替換#define函數
//#define函數經常會引發難以察覺的錯誤
#define CALL_WITH_MAX(a,b) f((a)>(b)?(a):(b))  //用宏寫函數最好爲所有實參加上括號
//但還是有一些問題
int a=5,b=0;
CALL_WITH_MAX(++a,b);   //a會被累加兩次
CALL_WITH_MAX(++a,b+10);  //a會被累加一次         //這些錯誤難以發覺

template<typename T>
inline void callWithMax(const T&a,const T&b)
{
    f(a>b?a:b);
}
  • 總之,對於單純常量,用const對象或enum替換#define
  • 對於宏函數,採用inline函數替換
儘可能使用const
  • const出現在星號左邊,表示被指物是常量;const出現在星號右側,表示指針自身是常量;兩邊都有表示被指物和指針都是常量

  • 在設計類的時候,一個原則就是對於不改變數據成員的成員函數都要在後面加 const,而對於改變數據成員的成員函數不能加 const。

    (1)有 const 修飾的成員函數(指 const 放在函數參數表的後面),只能讀取數據成員,不能改變數據成員;沒有 const 修飾的成員函數,對數據成員則是可讀可寫的。
    (2)常量(即 const)對象可以調用 const 成員函數,而不能調用非const修飾的函數。

  • 當non-const成員函數和const成員函數有相同的等價實現時,令non-const函數調用const版本避免代碼重複

確定對象被使用前已先被初始化
  • 確保每一個構造函數都將對象的每一個成員初始化。儘量採用初始化列表的方式進行初始化。
  • 爲了避免"跨編譯單元之初始化次序"問題,以local static對象替換non-local static對象
瞭解C++默默編寫並調用哪些函數
  • 編譯器會默默爲class創建default構造函數、copy構造函數、copy assignment操作符以及析構函數
若不想使用編譯器自動生成的函數,就應該明確拒絕
  • 爲了駁回編譯器自動提供的函數,可以將對應的成員函數聲明爲private並且不予以實現
  • 在C++11中可以直接在成員函數聲明後面添加“= delete”,就可以阻止調用。
爲多態基類聲明virtual析構函數

帶有多態性質的base class應該聲明一個virtual析構函數,不然對其base類型指針析構時,可能會出現局部銷燬的情況,因爲無法調用到derived class的析構函數。如果classes設計目的沒有打算作爲base classes,或者不是爲了具備多態性,那麼就不應該聲明virtual析構函數

別讓異常逃離析構函數
  • 析構函數不要吐出異常。如果一個被析構函數調用的函數可能拋出異常,析構函數應該捕捉任何異常,然後吞下他們或結束程序。
  • 會拋出異常的代碼不要放在析構函數中
不要在構造和析構過程中調用virtual函數

構造函數和析構函數中不要調用任何虛函數,也不要調用那些調用虛函數的函數。更加根本的理由在於:在derived class對象的base class構造期間,對象的類型是base class而非derived class

令operator=返回一個reference to *this

令賦值操作符返回一個reference to *this可以實現一個連鎖賦值,保持和內置類型、標準庫一致。

在operator=中處理“自我賦值”

處理賦值時將自己賦值給自己的情況

複製對象時勿忘其每一個成分
  • copying函數應該確保複製”對象內所有的成員變量“及”所有base class成分“
  • 不要嘗試以某個copying函數去實現另一個copying函數。應該將共同機能放進第三個函數中,並由兩個copying函數共同調用
以對象管理資源

將資源放進對象內,利用析構函數自動調用機制確保資源被釋放。儘量使用智能指針

在資源管理中小心copying行爲
在資源管理中提供對原始資源的訪問
成對使用new和delete時要採取相同形式

如果在new表達式中使用[],delete也要使用[];如果new中不使用[],delete中也不要使用[]。特別注意typedef,很具迷惑性。

以獨立語句將newed對象置入智能指針

以獨立語句將newed對象存儲於智能指針內,不然,一旦異常拋出,有可能導致難以察覺的資源泄露。即不要在給函數傳參數時直接定義臨時(匿名)的智能指針。應該先定義好智能指針對象,再將該對象傳遞給函數。

讓接口容易被正確使用,不易被誤用
  • 好的接口很容易被正確使用,不容易被誤用。你應該在你的所有接口中努力達成這些性質
  • 促進正使用的辦法包括接口的一致性,以及與內置類型的行爲兼容。
  • 阻止誤用的辦法包括建立新類型,限制類型上的操作,束縛對象值,以及消除客戶的資源管理責任
設計class猶如設計type

設計類時有很多問題需要思考,最好整個框架定好後再開始設計,並根據需求進行完善。

以pass-by-reference-const替換pass-by-value
  • pass-by-value會造成較多的構造函數與析構函數的開銷,採用pass-by-reference-const可以避免該開銷,必須加上const
  • 對於內建類型和STL迭代器、函數對象,pass-by-value是高效的
不要返回臨時對象的引用
  • 不要返回一個臨時對象的引用或指針
  • 不要返回堆上分配對象的引用
將類中變量聲明爲private
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章