日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]? ? ? ?先考慮一種情況,對一個已知對象進(jìn)行拷貝,編譯系統(tǒng)會自動調(diào)用一種構(gòu)造函數(shù)——拷貝構(gòu)造函數(shù),如果用戶未定義拷貝構(gòu)造函數(shù),則會調(diào)用默認(rèn)拷貝構(gòu)造函數(shù)。? ? ? ?先看一個例子,有一個學(xué)生類,數(shù)

? ? ? ?先考慮一種情況,對一個已知對象進(jìn)行拷貝,編譯系統(tǒng)會自動調(diào)用一種構(gòu)造函數(shù)——拷貝構(gòu)造函數(shù),如果用戶未定義拷貝構(gòu)造函數(shù),則會調(diào)用默認(rèn)拷貝構(gòu)造函數(shù)。

? ? ? ?先看一個例子,有一個學(xué)生類,數(shù)據(jù)成員時學(xué)生的人數(shù)和名字:

#includeusing?namespace?std;

class?Student
{
private:
	int?num;
	char?*name;
public:
	Student();
	~Student();
};

Student::Student()
{
	name?=?new?char(20);
	cout?<<?"Student"?<<?endl;

}
Student::~Student()
{
	cout?<<?"~Student?"?<<?(int)name?<<?endl;
	delete?name;
	name?=?NULL;
}

int?main()
{
	{//?花括號讓s1和s2變成局部對象,方便測試
		Student?s1;
		Student?s2(s1);//?復(fù)制對象
	}
	system("pause");
	return?0;
}


? ? ? ?執(zhí)行結(jié)果:調(diào)用一次構(gòu)造函數(shù),調(diào)用兩次析構(gòu)函數(shù),兩個對象的指針成員所指內(nèi)存相同,這會導(dǎo)致什么問題呢?name指針被分配一次內(nèi)存,但是程序結(jié)束時該內(nèi)存卻被釋放了兩次,會導(dǎo)致崩潰!


? ? ? ?這是由于編譯系統(tǒng)在我們沒有自己定義拷貝構(gòu)造函數(shù)時,會在拷貝對象時調(diào)用默認(rèn)拷貝構(gòu)造函數(shù),進(jìn)行的是淺拷貝!即對指針name拷貝后會出現(xiàn)兩個指針指向同一個內(nèi)存空間。


? ? ? ?所以,在對含有指針成員的對象進(jìn)行拷貝時,必須要自己定義拷貝構(gòu)造函數(shù),使拷貝后的對象指針成員有自己的內(nèi)存空間,即進(jìn)行深拷貝,這樣就避免了內(nèi)存泄漏發(fā)生。

? ? ? ? 添加了自己定義拷貝構(gòu)造函數(shù)的例子:

#includeusing?namespace?std;

class?Student
{
private:
	int?num;
	char?*name;
public:
	Student();
	~Student();
	Student(const?Student?&s);//拷貝構(gòu)造函數(shù),const防止對象被改變
};

Student::Student()
{
	name?=?new?char(20);
	cout?<<?"Student"?<<?endl;

}
Student::~Student()
{
	cout?<<?"~Student?"?<<?(int)name?<<?endl;
	delete?name;
	name?=?NULL;
}
Student::Student(const?Student?&s)
{
	name?=?new?char(20);
	memcpy(name,?s.name,?strlen(s.name));
	cout?<<?"copy?Student"?<<?endl;
}

int?main()
{
	{//?花括號讓s1和s2變成局部對象,方便測試
		Student?s1;
		Student?s2(s1);//?復(fù)制對象
	}
	system("pause");
	return?0;
}


? ? ? ? 執(zhí)行結(jié)果:調(diào)用一次構(gòu)造函數(shù),一次自定義拷貝構(gòu)造函數(shù),兩次析構(gòu)函數(shù)。兩個對象的指針成員所指內(nèi)存不同。
?總結(jié):淺拷貝只是對指針的拷貝,拷貝后兩個指針指向同一個內(nèi)存空間,深拷貝不但對指針進(jìn)行拷貝,而且對指針指向的內(nèi)容進(jìn)行拷貝,經(jīng)深拷貝后的指針是指向兩個不同地址的指針。
再說幾句:
當(dāng)對象中存在指針成員時,除了在復(fù)制對象時需要考慮自定義拷貝構(gòu)造函數(shù),還應(yīng)該考慮以下兩種情形:
1.當(dāng)函數(shù)的參數(shù)為對象時,實(shí)參傳遞給形參的實(shí)際上是實(shí)參的一個拷貝對象,系統(tǒng)自動通過拷貝構(gòu)造函數(shù)實(shí)現(xiàn);
2.當(dāng)函數(shù)的返回值為一個對象時,該對象實(shí)際上是函數(shù)內(nèi)對象的一個拷貝,用于返回函數(shù)調(diào)用處。

3.淺拷貝帶來問題的本質(zhì)在于析構(gòu)函數(shù)釋放多次堆內(nèi)存,使用std::shared_ptr,可以完美解決這個問題。

關(guān)于std::shared_ptr的原理和實(shí)現(xiàn)可參考:C++筆試題之smart pointer的實(shí)現(xiàn)

一個完整的自定義類實(shí)現(xiàn)可參考:C++筆試題之String類的實(shí)現(xiàn)


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關(guān)閉