天天看點

拷貝構造函數與指派運算符重載

拷貝構造函數

注意點

1.類聲明隻描述如何配置設定記憶體,并不會配置設定記憶體。是以,不要在類聲明中初始化靜态成員變量。 特殊情況:靜态成員是const或者是枚舉型時,則應在類聲明中初始化。

2.會用到複制構造函數的聲明:

point a(b);

point a = b;

point a = point b;

point *a = new point(b)

中間兩個聲明是等價的。并且有兩種可能性,一種直接使用拷貝構造函數建立對象,一種使用拷貝構造函數建立一個臨時變量,再調用重載的指派運算符。

3.按值傳遞和傳回對象也将調用拷貝構造函數。

4.由于第三點原因,我們在寫函數參數時,應該使用引用傳遞對象,可以節省使用拷貝構造函數的時間和建立新對象的空間。

5.在類對象建立時,要避免淺複制(即使用了預設拷貝構造函數),兩個對象指向同一段空間,遇到析構函數時,将會發生同一段空間被釋放兩次的情況,将會引發報錯。

6.當我們看到類中的資料成員有指針變量或者靜态資料成員時,需要主動提供一個顯式拷貝構造函數

常見格式(深複制)

StringBad::StringBad(const StringBad &st)
{
	num_string++;     // 修改靜态成員變量,符合我們第6個注意點
	len = st.len;     //  長度
	str = new char[len + 1];    // 配置設定了一段空間,加1的目的是預留給\0(字元串結束符)空間
	strcpy(str, st.str);    // 把字元串複制到配置設定的空間中
}
           

指派運算符重載

注意點

1.将一個已有對象指派給一個對象時,将會使用重載的指派運算符,在除初始化時,大部分兩個對象都有值了。

2.指派運算符不會産生新對象,是以不會對靜态成員變量産生影響。有人可能會産生疑惑,在初始化時,我們也要用到重載的指派運算符,那麼勢必需要修改靜态成員變量。其實,初始化,有兩種情況,之前已經說明了,細心的小夥伴已經發現了共同點,沒錯,初始化一定會使用拷貝構造函數,此時已經修改了靜态成員變量,不用再擔心了。

3.在重載指派運算符時,要避免将對象指派給自身。

常見格式

StringBad& StringBad::operator(const StringBad &st)
{
	if(this == &st)    // 首先檢查自我複制
	{
		return *this
	}
	delete[] str    // 釋放可能有的舊的内容,防止之後産生記憶體洩漏
	len = st.len    // 長度
	str = new char[len + 1]    // 配置設定一段新空間
	strcpy(str, st.str)    // 把字元串複制到配置設定的空間中,此時若剛剛不delete空間,則會産生記憶體洩漏!
	}
           

繼續閱讀