通過default構造函數出一個對象再對他指派比直接在構造時指定指派 差。
比如
string str("honey~");和
string str; str="honey~";效率就不一樣。
接下來講循環時的初始化,
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
class Base
{
public:
...
private:
string bm1,bm2;
};
class Derived
{
public:
Derived(){} //看起來是空的。
private:
stirng dm1,dm2,dm3;
};
Derived::Derived()
{
Base::Base();
try{dm1.string::string();}
catch(...)
{
Base::~Base();
throw;
}
try{dm2.string::string();}
catch(...)
{
dm1.string::~string();
Base::~Base();
throw;
}
try{dm3.std::string::string();}
catch(...)
{
dm2.string::~string();
dm1.string::~string();
Base::~Base();
throw;
}
}
pimpl idiom 将實作放入一個類,在接口類中定義一個智能指針指向實作類,進而達到與實作細目分離。