負數的右移位操作
負數的>>操作,結果取決於語言的實現,左邊空出的位置,可能填補0,也可能填補1。
靜態局部對象
內建類型的局部對象如果沒顯式初始化,則值就未初始化。靜態局部對象、全域對象,包括內建類型和使用者自訂類型,如果未提供初始化式,則編譯器自動初始化為0。
拷貝建構函式
A(A copy){…};是不允許的,如果允許,會造成無限的遞迴調用。正確的形參為const A& copy。複製操作符無此限制。
自訂String類的拷貝建構函式和賦值操作符的實現
實現的是有應當考慮異常安全性。(高品質編程P241)
賦值操作符實現須注意四個步驟:1、檢查自我賦值。2、分配新的記憶體資源,並拷貝內容。3、釋放原有的記憶體資源。4、返回本對象的引用。
除了上面的方法外,還可以通過自訂一個swap函數、調用拷貝建構函式來實現。
預設形參值
預設值應放在函數聲明中,不可放在函數定義中。如果有多個預設形參,則只能從後往前一直預設。
容器元素類型
凡是用作容器元素類型的class,都需要重載==、=、<等運算子。因為容器可能會使用它們來排序或者拷貝元素,某些泛型演算法都是假設元素類型已經重載了=、<等。
不能重載的運算子
有一些運算子是不允許重載的,一方面由於它們的右運算元是一個名字(比如成員名)而不是對象;另一方面是出於安全性的考慮,防止產生混亂和錯誤。不能重載的運算子有 1 . 2 .* 3 :: 4 ?: 5 sizeof typeid 6 四個類型轉換操作符
重載後置++和--
一元操作符一般重載為非靜態成員函數。重載後置的遞減、遞增操作符,為了和前置的區別,需要在聲明的時候,設定啞元。如Integer類中的後置++操作符重載:Integer operator++(int){…}。還需要注意的是,在進行++操作前,需要定義一個Integer temp = *this; 以便最後返回。
當自增和自減操作符應用於基礎資料型別 (Elementary Data Type)時,前置版本和後置版本在效率上沒有多大的差別。然而,當應用於使用者定義型別,尤其是大對象的時候,前置版本就會比後置版本的效率高許多。因為後置版本要建立一個臨時對象,並在返回後銷毀,返回的時候還會調用拷貝建構函式。
inline函數
較之宏定義,好處:1、可以在debug版本中調試(debug版本中其實沒有進行內聯)。2、編譯器可以對內嵌函式根據上下文程式進行最佳化,而不可也對普通函數最佳化,因為一旦進入函數體它也就脫離了環境內容。3、執行的時候可以進行類型檢查。
inline關鍵字必須與函數定義體放在一起才能使函數內聯,放在聲明處無效。inline只是對編譯器的一個申請,是否真正inline取決於編譯器。
內嵌函式以代碼膨脹為代價,換來函數調用參數壓站、跳轉、返回等開銷。一般把代碼較短,不含迴圈和複雜控制結構的函式宣告為內聯。建構函式和解構函式一般不可聲明為內聯,因為它們一般隱含很多函數調用。
C++中強制類型轉換
const_cast可用於去除一個對象的const/volatile屬性。reinterpret_cast可用於將一個整形轉換為一個指標,或者在兩種具象形指標間轉換。需要注意的是,void*轉換為具象形指標需要使用static_cast。
資料萃取
class Point{public: Point(float x); operator float() const //資料萃取、向外轉換 { return m_x; }private: float m_x;}
非explicit建構函式可以把其他類型對象隱式轉換為this對象,即向內轉換。C++還提供了相反的方向轉換方法,叫做自訂類型轉換運算子,它可以把this對象轉換為其他的資料類型對象。
類型轉換運算子定義以operator關鍵字開始,緊接著目標類型名和()。它沒有參數,實際上this就是參數;也沒有傳回型別,實際上函數名就是傳回型別。它只能定義為非靜態成員函數。
定義類型轉換運算子的好處在於,該類型的對象可以直接用在需要目標類型的地方,編譯器自動調用轉換函式完成轉換:
1: Point p2(100.25);
2: Integer aInt(100);
3: cout << p2 << endl; //100.25
4: cout << aInt << endl; //100
這樣我們就不需要為Point和Integer重載<<運算子了。