花了幾天時間,把《深入C++面向對象模型》看了一半的樣子。確實如BBS上的同學說的那樣,“帥呆了!”,絕對讓你停不下來的節奏。這本書是C++經典書單裏面的常客,《Effective C++》也是很多人推薦。說實話吧!我手頭有一本《Effective C++》,卻一直沒有看完,準確地說是我沒有在閱讀的過程中得到很多樂趣。不是黑《Effective C++》,只是這本書的寫作模式是條款式的。它的關注點在於“出什麼問題?”以及“如何避免?”,而不是爲什麼會這樣。相對來說,這本書還是比較偏工程應用,而《深入C++面向對象模型》卻常常在分析編譯器的一些細節,感覺更底層,更學術一些吧!
言歸正傳了,記一點拷貝構造函數相關的筆記。拷貝函數名爲“拷貝”,卻並不一定是無腦的copy。“無腦copy”的學名叫“Bitwise Copy”,就是每個bit都一起拷貝的方法。當一下四種情況出現的時候,Bitwise Copy Constructor就行了。
1、2、當class內含一個或則繼承一個存在copy constructor的類;
3、當class聲明瞭一個或多個virtual functions時;
4、當class派生自一個繼承串鏈,其中有一個或多個virtual base classes時。
前兩中情況下,編譯器必須將member或base class的copy constructors調用操作安插到被合成的copy constructor中;第三種情況主要是要準確設置vptr指向的位置;第四種情況中,是因爲虛基類的存在導致virtual base class的位置需要確定,所以不能簡單拷貝。
函數返回值的實現和拷貝構造函數的關係也是非常密切的,下面是cfront(第一個C++編譯器)的實現方法。原函數如下:
X bar()
{
X xx;
//處理 xx ...
rerurn xx;
}
轉換後的僞代碼:
//函數轉換
//以反映出copy constructor的應用
//C++僞代碼
void
bar(X& _result)
{
X xx;
//編譯器所產生的default constructor調用操作
xx.X::X();
//...處理xx
//編譯器所產生的copy constructor調用操作
_result.X::X(xx);
return;
}
然後編譯器必須轉換每一個bar()調用操作,以反映其新定義。X xx = bar();被轉化爲一下兩個語句://注意,不必施行default constructor
X xx;
bar(xx);
一個顯而易見的問題是程序效率。臨時變量和_result之間的拷貝無疑會降低程序效率。編譯器的優化方法如下://編譯器層面的優化:
X bar()
{
X xx;
//...處理xx
return xx;
}
//編譯器把其中的xx以_result取代:
void
bar(X &_result)
{
//default constructor被調用
//C++僞代碼
_result.X::X();
//...直接處理_result
return;
}
這種優化有時被稱爲Named Return Value(NRV),在對象比較大的情況下,應該是可以節省不少時間的。