C++進階之一
在實際工作中,發現大學C++教科書上的C++知識還不夠用,或者理解不夠深,為此這方面還得沖沖電。下面是簡單整理了以前不太熟悉的幾個點。
1. 構造和拷貝函數
l 賦值構造函數:T(T &)
l 賦值拷貝函數: operator = (T &)
l 移動構造函數: T(T &&)
l 移動拷貝函數:operator =(T&&)
一般如果類中有指針成員,建議 disable 掉賦值構造和賦值拷貝函數。而通常出於對性能優化的目的,可以使用移動構造函數和移動拷貝函數來減少冗余拷貝。
舉例說明:
class T {
T(int);
T(const T&);
Operator = (const T&);
T(const T&&);
}
int main() {
T a = T(1);
T && b = T(2);
}
上面T a 的初始化過程中,有一次構造一次拷貝;而T b就只有一次構造了。
2. virtual
l 限定虛函數:virtual func(….) ;
l 限定純虛函數: virtual func(….) =0 , 抽象類只有純虛函數
l 限定被繼承的基類,用作虛基類,避免子類擁有基類中重復的成員方法;
例如: class B: virtual A;
class C: virtual A;
class D: class B, class C; // 那麽D的對象中只有A的一份成員;
l 抽象類的析構函數一定是虛函數(個人的理解是對於裏面的虛函數可能用到的資源是不定的)
3. C++ 11 中的自動推斷變量類型auto 的使用
Auto 的使用極大地方便了枚舉器的使用,隱藏了枚舉的過程,舉例如下:
Auto x1=3.1415169;
Std::map<float, int> mymap;
For (auto it = mymap.begin; it != mymap.end(); it++) {
……
}
4. C++ 匿名函數 lamnda 的使用
本質就是去類臨時函數定義時的名稱,通過【】代替。這種函數通常在一些算法庫中的比較函數、判斷是否相等的臨時函數的定義中。
格式如下:
[capture](parameters)->return-type{body}
其中capture高速這個臨時函數,是否以及如何使用外部的變量,規則如下:
[] //未定義變量.試圖在Lambda內使用任何外部變量都是錯誤的.
[x, &y] //x 按值捕獲, y 按引用捕獲.
[&] //用到的任何外部變量都隱式按引用捕獲
[=] //用到的任何外部變量都隱式按值捕獲
[&, x] //x顯式地按值捕獲. 其它變量按引用捕獲
[=, &z] //z按引用捕獲. 其它變量按值捕獲
實例如下:
【】(int a, int b)->int (int z= a+b; return z);
5. 構造函數和析構函數執行的順序
具體規則如下:
l 如果對象的類型是global/static 等落在.data或者.bss段,那麽對於global的變量,先於main()函數執行構造;對於function domain的則在執行到的地方開始執行構造。析構函數按鏡像對稱的順序進行;
l 如果對象的類型是在棧上,在執行到代碼的地方開始構造,在作用域結束的地方析構;
l 如果對象的類型在堆上,根據顯式調用析構函數的順序執行;如果沒有顯式調用析構,在堆被系統釋放的時候調用析構函數;
l 對於多重繼承的情況,構造函數沿著從基類到子類的方向進行,而析構函數沿著相反方向執行。
C++進階之一