通過default建構函式出一個對象再對他賦值比直接在構造時指定賦值 差。
比如
string str("honey~");和
string str; str="honey~";效率就不一樣。
接下來講迴圈時的初始化,
/*
class A;
A a;
for(int i=0;i<n;i++) //1次構造,1次析構,n次賦值。
{a=**;}
*/
class A;
for(int i=0;i<n;i++) //n次構造,n次析構
{
A a(**);
}
//綜上,下面的情況好。
轉型分為舊式轉型和新式轉型。
舊式轉型: (T) expression
新式轉型:
1.const_cast<T>(expression) cast away the constness
將對象的常量性移除
2.dynamic_cast<T>(expression) safe downcasting
唯一不能用舊式轉型實現的轉型動作。不過可能耗費重大運行成本的動作。
3.reinterpret_cast <T>(expression) 低級轉型
例:int*->int
4.static_cast<T>(expression) 強迫隱式轉換。
例:non-const -> const ,int->double
pointer-to-base ->pointer-to-derived
void* -> typed 指標
現在運用舊式轉型符的時機是調用explicit建構函式。
handle:reference,指標,迭代器。
函數不要返回一個指向存取層級較低的成員函數。因為會降低封裝性。
成語函數返回對象內部的handle可能會使dangling。
下面來看異常:
異常安全函數保證:
1.基本承諾:異常不出錯即可能出於任何合法狀態。
2.強烈保證:異常返回前一狀態。
3.不投擲保證:不跑出異常。
如int f() throw(); //不是說不拋出異常,而是只要拋出異常,就導致嚴重錯誤。
動態分配不成功就 bad_alloc異常。
如果一個系統中有一個函數不具備異常安全性,則整個系統不具備異常安全性。
封裝,異常安全性。
inline函數
1.免除調用成本
2.如果函數體過大,則會換頁行為和降低指令快取裝置的擊中率。
3.對比函數本體和函數調用所產生的代碼長度。
4.因為inlining是編譯期行為,所以要在標頭檔中。
5.template通常也 是inline但不全是。
//此執行個體為了證明建構函式和解構函式最好不要inline<br />class Base<br />{<br /> public:<br /> ...<br /> private:<br /> string bm1,bm2;<br />};<br />class Derived<br />{<br /> public:<br /> Derived(){} //看起來是空的。<br /> private:<br /> stirng dm1,dm2,dm3;<br />};<br />Derived::Derived()<br />{<br /> Base::Base();<br /> try{dm1.string::string();}<br /> catch(...)<br /> {<br /> Base::~Base();<br /> throw;<br /> }<br /> try{dm2.string::string();}<br /> catch(...)<br /> {<br /> dm1.string::~string();<br /> Base::~Base();<br /> throw;<br /> }<br /> try{dm3.std::string::string();}<br /> catch(...)<br /> {<br /> dm2.string::~string();<br /> dm1.string::~string();<br /> Base::~Base();<br /> throw;<br /> }<br />}
pimpl idiom 將實現放入一個類,在介面類中定義一個智能指標指向實作類別,從而達到與實現細目分離。