天天看點

《深度探索c++對象模型》與《Effective c++》讀書筆記

Default Constructor與條款4:确定對象被使用前已先被初始化

  《深度探索c++對象模型》2.1 Default Constructor 的構造操作核心在于 default constructors … 在需要的時候被編譯器産生出來這句話,其中暗含編譯器的預設構造函數并不“可靠”,由此《Effectice C++》認為每個class最好擁有顯示的構造函數。

  随之帶來的問題是,如何寫好一個高效的構造函數?更具體的,如何配合使用編譯器預設構造函數,使構造函數不至于非常龐雜,同時不産生過多的臨時對象?這就需要了解《深度搜尋c++對象模型》中4個nontrival的構造函數,在這4種情況下,編譯器會輔助自動生成一些代碼:

  1. “帶有default constructor”的member class object
  2. “帶有default constructor”的base class object
  3. "帶有virtual function"的class
  4. “帶有virtual Base class”的class

  3、4條主要關乎虛表相關概念,在了解虛函數、虛基類使用的虛表技術後,便豁然開朗,在此先不作說明。本文重點将放在1、2條,以書上的一個例子進行闡述。

class Dopey {public: Dopey();};
class Sneezy {public:Sneezy(int);Sneezy();...};
class Bashful{public: Bashful();..};

class Snow_White
{
public:
	Dopey dopey_;
	Sneezy sneezy_;
	Bashful bashful_;
private:
int numble_;
string name_;
}
           

基于第一條原則,若沒有顯示書寫構造函數,編譯器将為其自動生成如下的預設構造函數:

Snow_White::Snow_White()
{
	dopey_.Deopy::Doepy();
	sneezy_.Sneezy::Sneezy();
	bashful_.Bashful::Bashful();	
	name_.string::string();
}
           

推薦的顯示構造函數寫法:

Snow_White::Snow_White(int numble,string name):sneezy_(1024),numble_(numble),name_(name)
{}

//将被編譯器擴充成:
Snow_White::Snow_White(int numble,string name)
{
	dopey_.Deopy::Doepy();
	sneezy_.Sneezy::Sneezy(1024);
	bashful_.Bashful::Bashful();	
	numble_ = numble;
	name_.string::string(name);
}
           

不推薦的寫法如下,在《Effective c++》中認為這種寫法屬于assign而非構造,《深度探索c++對象模型》則表明使用該種寫法,實際是在調用預設拷貝構造函數,而通常情況下預設拷貝構造函數将額外産生一個臨時對象,函數結束還需進行銷毀,是以該寫法是低效的。

Snow_White::Snow_White(int numble,string name):sneezy_(1024)
{
	numble_ = numble;
    name_ = name;
}
           

同時值得注意的是,在采用上述推薦寫法時的指派順序,最好按照定義的先後順序進行指派——因為編譯器會強行根據定義順序改變指派順序,確定自身邏輯和編譯器吻合。

class Snow_White
{
public:
	Dopey dopey_;
	Sneezy sneezy_;
	Bashful bashful_;
private:
int numble_;
string name_;
string name2_;
}

//這種寫法編譯器會自動改變
Snow_White::Snow_White(int numble,string name,string name2):sneezy_(1024),numble_(numble),name2_(name2),name(name_)
{}

           

繼續閱讀