最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++超詳細(xì)講解拷貝構(gòu)造函數(shù)

 更新時(shí)間:2022年06月02日 08:54:33   作者:iheal  
我們經(jīng)常會(huì)用一個(gè)變量去初始化一個(gè)同類(lèi)型的變量,那么對(duì)于自定義的類(lèi)型也應(yīng)該有類(lèi)似的操作,那么創(chuàng)建對(duì)象時(shí)如何使用一個(gè)已經(jīng)存在的對(duì)象去創(chuàng)建另一個(gè)與之相同的對(duì)象呢

構(gòu)造函數(shù)

只有單個(gè)形參,該形參是對(duì)本類(lèi)類(lèi)型對(duì)象的引用(一般常用const修飾),在用已存在的類(lèi)類(lèi)型對(duì)象創(chuàng)建新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用

拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個(gè)重載,因此顯式的定義了拷貝構(gòu)造,那么編譯器也不再默認(rèn)生成構(gòu)造函數(shù)。

特征

拷貝構(gòu)造也是一個(gè)特殊的成員函數(shù)

特征如下:

  • 拷貝構(gòu)造是構(gòu)造函數(shù)的一個(gè)重載;
  • 拷貝構(gòu)造的參數(shù)只有一個(gè)并且類(lèi)型必須是該類(lèi)的引用,而不是使用傳值調(diào)用,否則會(huì)無(wú)限遞歸;
  • 若沒(méi)有顯式定義拷貝構(gòu)造函數(shù),編譯器會(huì)自己生成一個(gè)默認(rèn)拷貝構(gòu)造,默認(rèn)的拷貝構(gòu)造函數(shù)對(duì)象按按內(nèi)存存儲(chǔ)和字節(jié)序完成拷貝,也叫淺拷貝;
class Date
{
public:
	Date(int year, int month, int day)
		:
		_year(year),
		_month(month),
		_day(day)
	{}
	void Display()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2001, 7, 28);
	Date d2(d1);
	d1.Display();
	d2.Display();
	return 0;
}

輸出:

2001-7-28

2001-7-28

對(duì)于那些直接管理著內(nèi)存資源的類(lèi)(含有指針變量),那么簡(jiǎn)單的值拷貝還頂?shù)米??顯然頂不住啊。

通過(guò)圖示說(shuō)明:

兩個(gè)string類(lèi)的對(duì)象指向了同一塊空間,這不就亂套了嗎,如果其中一個(gè)對(duì)象通過(guò)指針改變了指向內(nèi)存的數(shù)據(jù),那么另一個(gè)對(duì)象也會(huì)受到影響,這是我們不愿發(fā)生的,我們希望每個(gè)對(duì)象都能獨(dú)立運(yùn)作。

下面這個(gè)程序會(huì)崩潰

class String
{
public:
	String(const char* str = "songxin")
	{
		cout << "String(const char* str = \"songxin\")" << endl;
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	~String()
	{
		cout << "~String()" << endl;
		free(_str);
		_str = nullptr;
	}
private:
	char* _str;
};
int main()
{
	String s1;
	String s2(s1);
	return 0;
}

原因是兩個(gè)string類(lèi)的成員指針都指向一塊內(nèi)存,而它們又分別調(diào)用了一次析構(gòu)函數(shù),相當(dāng)于對(duì)同一塊內(nèi)存空間釋放了兩次,程序崩潰。

因此對(duì)于這種情況的對(duì)象,我們就不能再使用編譯器生成的默認(rèn)拷貝構(gòu)造了,而只能自己去顯式的定義拷貝構(gòu)造并且要實(shí)現(xiàn)深拷貝。

編譯器生成的拷貝構(gòu)造

編譯器默認(rèn)生成的拷貝構(gòu)造會(huì)做些什么呢?

  • 對(duì)于內(nèi)置類(lèi)型成員

? 完成值拷貝;

  • 對(duì)于自定義類(lèi)型成員

調(diào)用成員的拷貝構(gòu)造;

class Time
{
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		:
		_hour(hour),
		_minute(minute),
		_second(second)
	{}
	Time(Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
Time top(0, 1, 1);
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1, Time& t = top)
		:
		_year(year),
		_month(month),
		_day(day),
		_t(t)
	{}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	Time t(1, 1, 1);
	Date d1(2001, 7, 28,t);
	Date d2(d1);
	return 0;
}

如果默認(rèn)生成的拷貝構(gòu)造沒(méi)有調(diào)用Time類(lèi)成員的拷貝構(gòu)造,那么d2的_t的值應(yīng)該是(_hour = 0, _minute = 0, _second = 0),而這里最終的結(jié)果是d2中的_t和d2中的_t值相同。

這里Date類(lèi)中自動(dòng)生成的拷貝構(gòu)造函數(shù)的內(nèi)置類(lèi)型會(huì)進(jìn)行字節(jié)序拷貝,而對(duì)于自定義類(lèi)型_t調(diào)用了Time的拷貝構(gòu)造函數(shù)。

拷貝構(gòu)造的初始化列表

拷貝構(gòu)造是構(gòu)造函數(shù)的一個(gè)重載,因此拷貝構(gòu)造函數(shù)也是有初始化列表的,所以也建議在初始化列表階段完成對(duì)對(duì)象的初始化,養(yǎng)成良好習(xí)慣。

可以不顯式定義拷貝構(gòu)造函數(shù)的情況

  • 成員變量沒(méi)有指針;
  • 成員有指針,但并沒(méi)有管理內(nèi)存資源;

顯式定義拷貝構(gòu)造的誤區(qū)

之前一直存在這個(gè)誤區(qū):

我們都知道,編譯器生成的構(gòu)造函數(shù)在初始化列表會(huì)調(diào)用成員的構(gòu)造函數(shù),而我們顯式去定義構(gòu)造函數(shù)時(shí),即使我們不寫(xiě)也會(huì)在初始化列表去調(diào)用自定義類(lèi)型成員的構(gòu)造函數(shù)。

通過(guò)類(lèi)比,我就犯了一個(gè)低級(jí)錯(cuò)誤:

就是既然編譯器生成的拷貝構(gòu)造可以在初始化列表自動(dòng)調(diào)用自定義成員的拷貝構(gòu)造,那么我們顯式定義的拷貝構(gòu)造即使不寫(xiě),也會(huì)在初始化列表自動(dòng)去調(diào)用自定義成員的拷貝構(gòu)造。

于是我寫(xiě)出了如下代碼:

class Time
{
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		:
		_hour(hour),
		_minute(minute),
		_second(second)
	{}
	Time(Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
Time top(2, 2, 2);
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1, Time& t = top)
		:
		_year(year),
		_month(month),
		_day(day),
		_t(t)
	{}
	Date(Date& d)//顯式定義了拷貝構(gòu)造
	{
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	Time t(1, 1, 1);
	Date d1(2001, 7, 28,t);
	Date d2(d1);
	return 0;
}

通過(guò)監(jiān)視窗口查看d2調(diào)用拷貝構(gòu)造后的值:

并沒(méi)有拷貝成功。

我只顧著類(lèi)比它們的功能,可我恰恰忽略了拷貝構(gòu)造也是一種構(gòu)造函數(shù)啊,那么自然的初始化列表也是和普通構(gòu)造一樣,會(huì)去調(diào)用自定義類(lèi)的構(gòu)造函數(shù),不處理內(nèi)置類(lèi)型。只不過(guò)編譯器生成的是經(jīng)過(guò)處理的構(gòu)造函數(shù)達(dá)到了拷貝的效果。(太傻逼了這錯(cuò)誤)

結(jié)論

拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一種,它也有初始化列表,如果是編譯器生成的拷貝構(gòu)造,它會(huì)對(duì)內(nèi)置類(lèi)型做字節(jié)序拷貝,對(duì)自定義類(lèi)型成員會(huì)調(diào)用自定義成員的拷貝構(gòu)造。

可如果是我們顯式定義出的拷貝構(gòu)造,它也是有初始化列表的,但是它的初始化列表可不會(huì)去調(diào)用成員的拷貝構(gòu)造奧,而是和普通構(gòu)造函數(shù)一樣,對(duì)于內(nèi)置類(lèi)型成員不去初始化值,對(duì)于自定義類(lèi)型成員調(diào)用自定義成員的構(gòu)造函數(shù)而不是拷貝構(gòu)造函數(shù)。

到此這篇關(guān)于C++超詳細(xì)講解拷貝構(gòu)造函數(shù)的文章就介紹到這了,更多相關(guān)C++拷貝構(gòu)造函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++ Bellman-Ford算法的具體實(shí)現(xiàn)

    c++ Bellman-Ford算法的具體實(shí)現(xiàn)

    Bellman-Ford算法用于解決有邊數(shù)限制的最短路問(wèn)題,且可以應(yīng)對(duì)有負(fù)邊權(quán)的圖,本文主要介紹了c++ Bellman-Ford算法的具體實(shí)現(xiàn),感興趣的可以了解一下
    2021-06-06
  • C語(yǔ)言完整特性詳情

    C語(yǔ)言完整特性詳情

    這篇文章主要介紹了C# 10的相關(guān)資料方法,感興趣的朋友可以參考下文
    2021-08-08
  • 解析C++浮點(diǎn)數(shù)無(wú)效值的定義與無(wú)效值判定的小結(jié)

    解析C++浮點(diǎn)數(shù)無(wú)效值的定義與無(wú)效值判定的小結(jié)

    本篇文章是對(duì)C++中浮點(diǎn)數(shù)無(wú)效值的定義與無(wú)效值的判定進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語(yǔ)言實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式

    C語(yǔ)言實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++內(nèi)存管理詳細(xì)解析

    C++內(nèi)存管理詳細(xì)解析

    這篇文章主要給大家分享的是C++內(nèi)存管理的詳細(xì)內(nèi)容學(xué)習(xí),下面文章圍繞C++內(nèi)存管理的相關(guān)資料展開(kāi)具體學(xué)習(xí)內(nèi)容,需要的朋友可以參考一下,希望對(duì)你有所幫助
    2021-11-11
  • C++深入分析回顧函數(shù)重載

    C++深入分析回顧函數(shù)重載

    C++ 允許多個(gè)函數(shù)擁有相同的名字,只要它們的參數(shù)列表不同就可以,這就是函數(shù)的重載(Function Overloading),借助重載,一個(gè)函數(shù)名可以有多種用途
    2022-06-06
  • C++ 實(shí)現(xiàn)求最大公約數(shù)和最小公倍數(shù)

    C++ 實(shí)現(xiàn)求最大公約數(shù)和最小公倍數(shù)

    這篇文章主要介紹了c++ 實(shí)現(xiàn)求最大公約數(shù)和最小公倍數(shù)的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 基于Qt制作一個(gè)定時(shí)關(guān)機(jī)的小程序

    基于Qt制作一個(gè)定時(shí)關(guān)機(jī)的小程序

    這篇文章主要為大家詳細(xì)介紹了如何基于Qt制作一個(gè)有趣的定時(shí)關(guān)機(jī)的小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • 淺談C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換

    淺談C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換

    這篇文章主要介紹了C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C語(yǔ)言排序之?堆排序

    C語(yǔ)言排序之?堆排序

    這篇文章主要介紹了C語(yǔ)言排序之堆排序,文章基于C語(yǔ)言的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,具有一定的參考資料,需要的小伙伴可以參考一下
    2022-04-04

最新評(píng)論

通榆县| 盐城市| 汶川县| 阳高县| 芜湖县| 林周县| 隆尧县| 肇东市| 阳新县| 谷城县| 遂川县| 桦甸市| 乐山市| 汤原县| 太白县| 邯郸县| 陵水| 泾川县| 木兰县| 尉犁县| 泾川县| 新闻| 永清县| 北碚区| 保定市| 秦皇岛市| 长葛市| 秀山| 绵阳市| 高清| 化隆| 六枝特区| 丰镇市| 绥中县| 珲春市| 布尔津县| 伊宁市| 当阳市| 阿拉尔市| 湖口县| 台南县|