十七、拷貝構造和拷貝賦值
1、深拷貝和淺拷貝
拷貝構造:
1)如果一個類包含指針形式的成員變量,缺省的拷貝構造函數只會複製指針本身,而不會複製指針所指向的內容,這種拷貝稱爲淺拷貝。
2)淺拷貝將導致不同對象間的數據共享,如果數據是在堆區,在析構時會引發"double free"
異常;
3)因此必須定義一個支持複製指針所指向內容的拷貝構造函數,即深拷貝。
拷貝賦值:
在類中編譯器會提供一個缺省的拷貝賦值操作符函數,完成兩個對象的賦值操作,但是和缺省拷貝構造類似,是淺拷貝。爲了得到深拷貝的效果,必須自己定義一個支持深拷貝的拷貝賦值函數。
類型& operator=(const 類名& that){
1)防止自賦值
2)分配新資源(類似買手機,新手機到了,再扔舊手機,更妥當些)
3)釋放舊資源
4)拷貝新數據
5)返回自引用
}
練習:實現string類
十八、靜態成員(static)
1、靜態成員變量
class 類名{
static 數據類型 變量; // 聲明
};
數據類型 類名::變量 = 初值; // 定義和初始化
1)靜態成員變量類似全局變量,內存在全局區,所以它不屬於對象,也不能在構造函數中定義和初始化,需要在類的外部單獨定義和初始化。
2)使用方法
類名::靜態成員變量;
(常用)
對象.靜態成員變量;
2、靜態成員函數
class 類名{
static 返回類型 函數名(形參表){..};
};
1)在靜態成員函數中沒有this指針;
2)使用方法:
類名::靜態成員函數(實參表);
(常用)
對象.靜態成員函數(實參表);
注意:
靜態成員函數中只能訪問靜態成員,而在非靜態成員函數既能訪問靜態成員,也能訪問非靜態成員。
3、單例模式
一個類只允許創建一個對象。
1)禁止在類的外部隨意創建對象:私有化構造函數;
2)在類的內部自己維護唯一的對象:靜態成員變量;
3)提供獲取和訪問該對象的方法:靜態成員函數;
class A{
public:
A& get(void){
return a;
}
private:
A(void);
A(const A&);
static A a;
};
4)創建方式:
a. 餓漢式:無論單例對象用或不用,程序啓動即創建;
b. 懶漢式:單例對象用的時候再創建,不用時即銷燬;
練習1:自己寫一遍String的實現;
練習2:自己實現單例模式 . .