1. 仔細區分 pointers 和 references express
references和pointers的差異描述以下:數組
pointer:當須要考慮"不指向任何對象"時,或者是考慮"在不一樣時間指向不一樣對象"的能力時,應該採用pointer。前一種狀況能夠將pointer設爲null,後一種能夠改變pointer所指對象。緩存
reference:當肯定"老是會表明某個對象",並且"一旦表明了該對象就不能再改變",那應該使用reference。 reference不能爲空,所以無需作判空操做,相對pointer使用效率更高。某些操做符重載 operator[],operator= 採用reference實現。安全
結論: 當知道須要指向某個東西,並且毫不會改變指向其餘東西,或是當實現一個操做符而其語法需求沒法由pointers實現,就應選擇references。 其任什麼時候候,請採用 pointers。函數
2. 最好使用 C++ 轉型操做符 spa
因爲舊式的c轉型幾乎容許任何類型轉換爲任何其餘類型,這樣是十分拙劣的,若是每次轉型可以精確地指明轉型意圖,會更好。還有就是舊式轉型難以辨識,致使查看代碼時,會遺漏轉型操做。C++ 引進4個新的轉型操做符:指針
舊式 C 轉型: code
(type) expression
C++ 轉型: 對象
``` 1. static_castdynamic_cast
用來執行繼承體系中"安全的向下轉型或者跨系轉型動做",咱們能夠利用dynamic_cast,將 "指向父類對象的指針或引用" 轉型爲 "指向子類對象的指針或者引用"
,並得知是否轉型成功,轉型失敗會返回一個null指針(當轉型對象時指針)或一個exception(當轉型對象時reference)
const_cast
改變表達式常量性(constness)或者 變易性(volatileness)
reinterpret_cast
與編譯平臺相關,不具備移植性。最經常使用用途是轉換 "函數指針" 類型,不到非用不可的地步不用,由於某些狀況下會出現轉型不正確。
例如:
typedef void (*FuncPtr)();
FuncPtr funcPtrArrary[10];
int doSomething();
funcPtrArrary[0] = reinterpret_cast
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">若是你想爲一個不涉及繼承機制的類型執行轉型動做,可以使用static_cast;要改變常量性,必須使用const_cast;涉及繼承機制,使用dynamic_cast 或者 static_cast; reinterpret_cast 把一個指針轉換成一個整數,也能夠把一個整數轉換成一個指針。</p> <p style="color: #AD5D0F;font-weight: bold;font-size: 20px; font-family: '微軟雅黑';">3. 絕對不要以多態的方式處理數組 </p> ------ <p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">大體代碼以下:</p>
// 簡單繼承關係
class BST{...};
class BalancedBST: public BST{...};
// 打印接口
void printfBSTArray(ostream& s, const BST arrry[], int numElements)
{
for(int i = 0; i < numElements; ++i){
s << array[i];
}
}
BalancedBST bBSTArray[10];
...
printfBSTArray(cout, bBSTArray, 10); // 發生不可預期問題
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">上述代碼中,<font color="#ff0000">編譯器爲了可以訪問整個數組,編譯器必須有能力決定數組對象大小,編譯器認爲大小爲BST類大小,可是咱們傳入的是其子類,而子類對象大小確定是大於父類的,所以致使這裏會發生不可預期錯誤</font>。 </p> <p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-weight: bold; font-family: '微軟雅黑';">多態和指針算術不能混用。而數組對象幾乎老是會涉及指針的算術運算,因此數組和多態不要混用。</p> <p style="color: #AD5D0F;font-weight: bold;font-size: 20px; font-family: '微軟雅黑';">4. 非必要不提供 default constructor </p> ------ <p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">由不帶參數的構造函數,或者爲全部的形參提供默認實參的構造函數,被稱爲默認構造函數(default constructor)。</p>
class foo
{
public:
foo(); // 默認構造函數
...
};
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">在一個完美世界中,凡能夠"合理的從無到有生成對象"的class,都應該內含默認構造函數,而"必須有某些外來信息才能生成對象"的class,則沒必要擁有默認構造函數。<font color="#ff0000">可是,當一個類缺少default constructor,使用時會受到限制。</font></p>
class foo
{
public:
foo(int Id); // 構造函數
...
};
foo bestfoo[10]; // 錯誤! 沒法調用構造函數
foo *best = new foo[10]; // 錯誤! 沒法調用默認構造函數
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">有介紹三種辦法來解決無默認構造函數的限制:</p> <p style="font-size: 15px; letter-spacing:1px; font-family: '微軟雅黑';">1. non-heap 數組</p>
foo fooTest[] = {foo(1), foo(2), foo(3)}; // 構造函數得到id,能夠成功
<p style="font-size: 15px; letter-spacing:1px; font-family: '微軟雅黑';">2. 指針數組。 缺點:指針數組要刪除,不然內存泄漏;保存指針,浪費內存。</p>
typedef foo* foo_ptr;
foo_ptr bestfoo[10]; // 沒問題,存在的指針,不用調用構造函數
foo_ptr *best = new foo_ptr[10] // 也沒問題,數組堆上存的是指針
for(int i = 0; i < 10; ++i){
best[i] = new foo(Id number); // 傳入ID 初始化對象
}
<p style="font-size: 15px; letter-spacing:1px; font-family: '微軟雅黑';">3. placement new。分配內存時可指定內存位置。</p>
// 首先申請一塊適當大小的緩存,能夠是堆上的,也能夠是其餘特殊緩存(例如共享內存)
void *rawMemory = operator new;
// 讓 best 指針指向該塊內存首地址
foo* best = static_cast<foo*>(rawMemory);
// 而後利用 placement new 構造內存中的 foo 對象
for(int i = 0; i < 10; ++i){
new (&best[i]) foo(Id number); // (&best[i]) : 內存位置
}
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-weight: bold; font-family: '微軟雅黑';"><font color="#ff0000">缺少 default constructor 類的第二個缺點,將不適用於許多基於模板實現的容器類</font>。</p> <p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-weight: bold; font-family: '微軟雅黑';"><font color="#ff0000">第三個缺點,虛基類沒有默認構造函數,將致使全部繼承類都要注意提供虛基類構造函數自變量,十分麻煩</font>。</p> <p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微軟雅黑';">缺少默認構造雖然會致使上述三種限制,可是若是不須要默認構造函數的類卻加了默認構造函數,將致使該類內部member functions邏輯變得複雜,以及影響調用該類的客戶代碼的效率。 所以非必要不提供 default constructor。</p> <p style="font-size: 15px;text-indent:60em;letter-spacing:1px; font-family: '微軟雅黑';">2018年10月1日14:59:02</p>