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

C++中的復(fù)制構(gòu)造函數(shù)詳解

 更新時(shí)間:2021年09月18日 11:28:32   作者:天上掉下個(gè)我  
今天小編就為大家分享一篇關(guān)于關(guān)于C++復(fù)制構(gòu)造函數(shù)的實(shí)現(xiàn)講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧

普通變量的復(fù)制

有時(shí)我們會(huì)在定義一個(gè)變量的同時(shí)使用另一個(gè)變量來初始化它。

int a_variable=12;
int new_variable(a_variable);

通過已有的同類型變量來初始化自身很有用。
對(duì)自定義類型的對(duì)象是否可以通過一個(gè)存在的對(duì)象方便的復(fù)制呢?

復(fù)制構(gòu)造函數(shù)

復(fù)制構(gòu)造函數(shù)又叫做拷貝構(gòu)造函數(shù),它只有一個(gè)參數(shù)(既然需要復(fù)制,一個(gè)就夠了,若傳入兩個(gè)相同對(duì)象則沒有意義,若傳入兩個(gè)不同的對(duì)象,就沒必要叫做復(fù)制構(gòu)造函數(shù)了),參數(shù)類型為本類的引用。

如果程序員沒有編寫復(fù)制構(gòu)造函數(shù),編譯器會(huì)自動(dòng)生成復(fù)制構(gòu)造函數(shù),在復(fù)制構(gòu)造函數(shù)中按照成員變量進(jìn)行逐字節(jié)復(fù)制(初學(xué)可以這樣理解,實(shí)際上,個(gè)別編譯器并不總是會(huì)自動(dòng)生成復(fù)制構(gòu)造函數(shù),它們可能采用直接將源對(duì)象的各個(gè)值復(fù)制到目標(biāo)對(duì)象對(duì)應(yīng)的成員變量上,后面會(huì)介紹這種情況)。

class MyDate
{
	int day_;
	int year_;
public:
	MyDate(int day, int year)
	{
		day_ = day;
		year_ = year;
	}
	MyDate(const MyDate& date)
	{
		day_ = date.day_;
		year_ = date.year_;
		cout << "Date類的復(fù)制構(gòu)造函數(shù)執(zhí)行了!" << endl;
	}
	~MyDate() {}
};
void test()
{
	MyDate date1(12, 2021);
	MyDate date2(date1);
}
int main()
{
	test();
	system("pause");
	return 0;
}

執(zhí)行為:

在這里插入圖片描述

對(duì)于MyDate(const MyDate& date)參數(shù)列表中的const,因?yàn)閺?fù)制構(gòu)造函數(shù)參數(shù)另一個(gè)對(duì)象引用,如果不加const修飾,在此復(fù)制構(gòu)造函數(shù)中可能會(huì)改變?cè)瓕?duì)象的內(nèi)容,為了安全起見,應(yīng)加盡加。

如果程序員編寫了復(fù)制構(gòu)造函數(shù),則編譯器就不會(huì)生成默認(rèn)復(fù)制構(gòu)造函數(shù)了(所以編寫了復(fù)制構(gòu)造函數(shù)之后就盡量在函數(shù)體內(nèi)實(shí)現(xiàn)復(fù)制操作,不要定義了復(fù)制構(gòu)造函數(shù)卻不完全或不實(shí)現(xiàn)復(fù)制操作)。

另一方面,所有的構(gòu)造函數(shù)(包括復(fù)制構(gòu)造函數(shù))、析構(gòu)函數(shù)都無法從父類繼承,只能自己實(shí)現(xiàn)。

構(gòu)造函數(shù)如果只有一個(gè)參數(shù)且這個(gè)參數(shù)為本類對(duì)象,就會(huì)與復(fù)制構(gòu)造函數(shù)起沖突。如圖:

在這里插入圖片描述

復(fù)制構(gòu)造函數(shù)的三種調(diào)用

復(fù)制構(gòu)造函數(shù)在以下3種情況下會(huì)被調(diào)用:

1.當(dāng)使用一個(gè)A類型對(duì)象去初始化另一個(gè)A類型的對(duì)象時(shí)(剛創(chuàng)建好的,已創(chuàng)建好的不算),會(huì)調(diào)用復(fù)制構(gòu)造函數(shù)。注意觀察以下代碼:

Date date1(12,2012);//創(chuàng)建一個(gè)date1對(duì)象
Date date2(date1);//調(diào)用復(fù)制構(gòu)造函數(shù)
Date date3=date1;//也會(huì)調(diào)用復(fù)制構(gòu)造 函數(shù)
date2=date1;//date2已存在,不會(huì)調(diào)用復(fù)制構(gòu)造函數(shù),會(huì)調(diào)用賦值=操作函數(shù)

在這里插入圖片描述

可以看到復(fù)制構(gòu)造函數(shù)只調(diào)用了兩次。

2.我們都知道C++傳參有傳值和傳引用(指針本質(zhì)上是傳值,傳的是實(shí)參的地址)。如果函數(shù)參數(shù)是一個(gè)自定義對(duì)象,那么會(huì)調(diào)用該自定義對(duì)象的復(fù)制構(gòu)造函數(shù)。

在傳值的時(shí)候,編譯器會(huì)開辟一個(gè)空間(創(chuàng)建了一個(gè)臨時(shí)對(duì)象)存儲(chǔ)實(shí)參的值(這個(gè)過程會(huì)將實(shí)參的各個(gè)值分配復(fù)制給臨時(shí)對(duì)象),再將該值壓入棧中。

//類聲明略
void TestFunction(MyDate date)
{
	cout << "TestFunction()執(zhí)行了!" << endl;
}
void test()
{
	MyDate date1(12, 2021);
	TestFunction(date1);
}
//main函數(shù)略

結(jié)果如下:

在這里插入圖片描述

3.如果函數(shù)的返回值是類MyDate的對(duì)象,則函數(shù)返回時(shí),會(huì)調(diào)用該對(duì)象的復(fù)制構(gòu)造函數(shù)。

//類聲明略
MyDate TestFunction2()
{
	MyDate date1(12, 2021);
	cout << &date1 << endl;
	return date1;
}
void test()
{
	cout << &TestFunction2() << endl;
}
//main函數(shù)省略

從復(fù)制構(gòu)造函數(shù)內(nèi)的輸出被兩個(gè)地址輸出夾住即可看出在哪里調(diào)用了復(fù)制構(gòu)造函數(shù)。

在這里插入圖片描述

復(fù)制構(gòu)造函數(shù)的禁用

如果不希望自定義類型的復(fù)制構(gòu)造函數(shù)被調(diào)用。

僅僅不編寫復(fù)制構(gòu)造函數(shù)是不行的,編譯器可能會(huì)自動(dòng)生成默認(rèn)的復(fù)制構(gòu)造函數(shù)。應(yīng)該使用private修飾復(fù)制構(gòu)造函數(shù)(這時(shí)編譯器就不會(huì)生成自動(dòng)復(fù)制構(gòu)造函數(shù)),此時(shí)不要實(shí)現(xiàn)這個(gè)復(fù)制構(gòu)造函數(shù),如下:

在這里插入圖片描述

這樣便既禁止了用戶調(diào)用此復(fù)制構(gòu)造函數(shù),又禁止了用戶通過其他成員函數(shù)或友元函數(shù)間接地調(diào)用它(如果我們僅僅把復(fù)制構(gòu)造函數(shù)聲明為private,聲明并實(shí)現(xiàn)了復(fù)制構(gòu)造函數(shù),雖然避免了用戶直接調(diào)用,但成員函數(shù)和友元函數(shù)還是可以調(diào)用,只有不實(shí)現(xiàn)它才能永絕后患)。

Bjarne Stroustrup認(rèn)為如果你希望禁止某些操作,就把它定義為一個(gè)私有的成員函數(shù)即可。

深拷貝與淺拷貝

如果成員變量含有指針類型,默認(rèn)復(fù)制構(gòu)造函數(shù)并不會(huì)將指針指向的內(nèi)存中的值進(jìn)行賦值,僅僅將指針存儲(chǔ)的值(也就是一個(gè)地址)復(fù)制了一次(與我們所希望的不一致)。這時(shí)兩個(gè)指針指向了同一塊內(nèi)存空間,一旦一種一個(gè)指針?biāo)鶎俚膶?duì)象聲明周期結(jié)束,會(huì)調(diào)用它自己的析構(gòu)函數(shù)回收指針指向的內(nèi)存空間。這時(shí)另一個(gè)指針遍指向了一個(gè)垃圾值,這個(gè)指針也變?yōu)榱丝諔抑羔?。以上就是我們常提到的淺拷貝。

實(shí)際開發(fā)當(dāng)中要竭力避免以上清情況的發(fā)生(當(dāng)成員變量含有指針或動(dòng)態(tài)分配內(nèi)存等情況)。

深拷貝如下:

class MyDate
{
private:
	char* buffer_;
public:
	MyDate(const char *init);//實(shí)現(xiàn)略
	MyDate(const MyDate &date)
	{
		if(date.buffer_!=nullptr)
		{
			buffer_=new char[strlen(date.buffer_)+1];
			strcpy(buffer_,date.buffer_);
		}
		else
		{
			buffer=nullptr;
		}
	}
}

復(fù)制構(gòu)造函數(shù)先檢查date中的buffer_的字符串大小,然后分配此大小+1的內(nèi)存給新創(chuàng)建的對(duì)象的buffer_(strlen函數(shù)不會(huì)計(jì)算'\0'字符),最后使用strcpy函數(shù)將date的buffer_指向的內(nèi)存中的內(nèi)容復(fù)制到新創(chuàng)建的對(duì)象的buffer_所指向的空間(strcpy函數(shù)會(huì)吧'\0'字符一并復(fù)制)。最后實(shí)現(xiàn)了兩個(gè)指針指向了不同的存儲(chǔ)空間(兩個(gè)空間的內(nèi)容相同)。

在這里插入圖片描述

如果我們要編寫需要字符的成員時(shí),盡量使用string。它會(huì)像其他成員變量一樣進(jìn)行復(fù)制,因?yàn)閟tring有自己的復(fù)制構(gòu)造函數(shù)。

一定會(huì)生成默認(rèn)復(fù)制構(gòu)造函數(shù)嗎?

我們前面提到如果程序員沒有定義自己的復(fù)制構(gòu)造函數(shù),編譯器會(huì)為我們生成一個(gè)默認(rèn)復(fù)制構(gòu)造函數(shù)。

實(shí)際上以下4中情況編譯器會(huì)為我們生成默認(rèn)復(fù)制構(gòu)造函數(shù)。

1.沒有為類編寫復(fù)制構(gòu)造函數(shù),但該類含有自定義類型或string等類型作為成員變量時(shí)。

2.沒有為類編寫復(fù)制構(gòu)造函數(shù),但該類繼承了一個(gè)含有復(fù)制構(gòu)造函數(shù)的類時(shí),編譯器會(huì)生成默認(rèn)復(fù)制構(gòu)造函數(shù),在該函數(shù)中調(diào)用父類的復(fù)制構(gòu)造函數(shù)。

3.沒有為類編寫復(fù)制構(gòu)造函數(shù),但是該類定義了虛函數(shù)或者該類的父類定義了虛函數(shù)。,

4.沒有為類編寫復(fù)制構(gòu)造函數(shù),但是該類有虛基類。

參考

The C++ Programming Language (美) Bjarne Stroustrup

Thinking in C++ Volume One:Introduction toStandard C++ (美)Bruce Eckel

C++新經(jīng)典 對(duì)象模型 王建偉

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • C/C++ 讀取16進(jìn)制文件的方法

    C/C++ 讀取16進(jìn)制文件的方法

    下面小編就為大家?guī)硪黄狢/C++ 讀取16進(jìn)制文件的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • 淺談C++中虛函數(shù)實(shí)現(xiàn)原理揭秘

    淺談C++中虛函數(shù)實(shí)現(xiàn)原理揭秘

    下面小編就為大家?guī)硪黄獪\談C++中虛函數(shù)實(shí)現(xiàn)原理揭秘。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • 淺析VC++中的頭文件包含問題

    淺析VC++中的頭文件包含問題

    類中盡量采用指針或引用方式調(diào)用其它類,這樣就可以只聲明class xxx了。并且這也符合資源最優(yōu)利用,更利于使用多態(tài)
    2013-09-09
  • 解析C++11的std::ref、std::cref源碼

    解析C++11的std::ref、std::cref源碼

    這篇文章主要介紹了解析C++11的std::ref、std::cref源碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • OpenCV利用對(duì)比度亮度變換實(shí)現(xiàn)水印去除

    OpenCV利用對(duì)比度亮度變換實(shí)現(xiàn)水印去除

    OpenCV中去除水印最常用的方法是inpaint,通過圖像修復(fù)的方法來去除水印。本文將介紹另一種方法:利用對(duì)比度亮度變換去除水印,需要的朋友可以參考一下
    2021-11-11
  • C++編程中new運(yùn)算符的使用學(xué)習(xí)教程

    C++編程中new運(yùn)算符的使用學(xué)習(xí)教程

    這篇文章主要介紹了C++編程中new運(yùn)算符的使用學(xué)習(xí)教程,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • C語言中利用封裝好的函數(shù)實(shí)現(xiàn)英文字母的大小寫轉(zhuǎn)換

    C語言中利用封裝好的函數(shù)實(shí)現(xiàn)英文字母的大小寫轉(zhuǎn)換

    這篇文章主要介紹了C語言中利用封裝好的函數(shù)實(shí)現(xiàn)英文字母的大小寫轉(zhuǎn)換,需要的朋友可以參考下
    2017-10-10
  • C++遍歷文件夾下文件的方法

    C++遍歷文件夾下文件的方法

    這篇文章主要介紹了C++遍歷文件夾下文件的方法,實(shí)例分析了C++針對(duì)文件夾遍歷的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 帶你分分鐘玩轉(zhuǎn)C語言指針

    帶你分分鐘玩轉(zhuǎn)C語言指針

    c語言指針其實(shí)是一個(gè)整形變量,與其它數(shù)據(jù)不同的是,它的作用是用來存儲(chǔ)其它變量的地址,下面這篇文章主要給大家介紹了關(guān)于C語言指針的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 利用Matlab編寫簡易版連連看小游戲

    利用Matlab編寫簡易版連連看小游戲

    連連看作為經(jīng)典的小游戲,一定是很多人的回憶吧。本文將用Matlab實(shí)現(xiàn)這一經(jīng)典的游戲,文中示例代碼具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評(píng)論

剑阁县| 望江县| 女性| 阳谷县| 综艺| 闻喜县| 台南市| 潞西市| 衡阳市| 长治县| 潮安县| 孟村| 奉化市| 杂多县| 焦作市| 屯门区| 双鸭山市| 西宁市| 读书| 娱乐| 麻城市| 德阳市| 务川| 中阳县| 朝阳县| 唐河县| 玛多县| 绵竹市| 榆树市| 普格县| 寻甸| 项城市| 湘乡市| 车致| 比如县| 新邵县| 柏乡县| 白河县| 南昌市| 肥乡县| 嵊泗县|