欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

普通變量的復(fù)制

有時我們會在定義一個變量的同時使用另一個變量來初始化它。

int a_variable=12;
int new_variable(a_variable);

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

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

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

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

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í)行為:

在這里插入圖片描述

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

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

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

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

在這里插入圖片描述

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

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

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

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

在這里插入圖片描述

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

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

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

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

結(jié)果如下:

在這里插入圖片描述

3.如果函數(shù)的返回值是類MyDate的對象,則函數(shù)返回時,會調(diào)用該對象的復(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)的輸出被兩個地址輸出夾住即可看出在哪里調(diào)用了復(fù)制構(gòu)造函數(shù)。

在這里插入圖片描述

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

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

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

在這里插入圖片描述

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

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

深拷貝與淺拷貝

如果成員變量含有指針類型,默認復(fù)制構(gòu)造函數(shù)并不會將指針指向的內(nèi)存中的值進行賦值,僅僅將指針存儲的值(也就是一個地址)復(fù)制了一次(與我們所希望的不一致)。這時兩個指針指向了同一塊內(nèi)存空間,一旦一種一個指針所屬的對象聲明周期結(jié)束,會調(diào)用它自己的析構(gòu)函數(shù)回收指針指向的內(nèi)存空間。這時另一個指針遍指向了一個垃圾值,這個指針也變?yōu)榱丝諔抑羔槨R陨暇褪俏覀兂L岬降臏\拷貝。

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

深拷貝如下:

class MyDate
{
private:
	char* buffer_;
public:
	MyDate(const char *init);//實現(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)建的對象的buffer_(strlen函數(shù)不會計算'\0'字符),最后使用strcpy函數(shù)將date的buffer_指向的內(nèi)存中的內(nèi)容復(fù)制到新創(chuàng)建的對象的buffer_所指向的空間(strcpy函數(shù)會吧'\0'字符一并復(fù)制)。最后實現(xiàn)了兩個指針指向了不同的存儲空間(兩個空間的內(nèi)容相同)。

在這里插入圖片描述

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

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

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

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

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

2.沒有為類編寫復(fù)制構(gòu)造函數(shù),但該類繼承了一個含有復(fù)制構(gòu)造函數(shù)的類時,編譯器會生成默認復(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)典 對象模型 王建偉

總結(jié)

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

相關(guān)文章

  • C++實現(xiàn)LeetCode(179.最大組合數(shù))

    C++實現(xiàn)LeetCode(179.最大組合數(shù))

    這篇文章主要介紹了C++實現(xiàn)LeetCode(179.最大組合數(shù)),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • c++中引用和指針的區(qū)別和聯(lián)系

    c++中引用和指針的區(qū)別和聯(lián)系

    許多人對于引用和指針的區(qū)別與聯(lián)系很糾結(jié)(包括我在內(nèi)O(∩_∩)O哈哈~),最近看到一篇關(guān)于引用和指針區(qū)別和聯(lián)系的文章,感覺茅塞頓開,在這里和大家分享下
    2014-04-04
  • C語言詳細分析貪心策略中最小生成樹的Prime算法設(shè)計與實現(xiàn)

    C語言詳細分析貪心策略中最小生成樹的Prime算法設(shè)計與實現(xiàn)

    最小生成樹的問題還是比較熱門的,最經(jīng)典的莫過于Prime算法和Kruskal算法了,這篇博文我會詳細講解Prime算法的設(shè)計思想與具體代碼的實現(xiàn),不要求數(shù)據(jù)結(jié)構(gòu)學(xué)的有多好,只要跟著我的思路來,一步一步的分析,調(diào)試,終能成就自己,那就讓我們開始吧
    2022-05-05
  • Qt 實現(xiàn)桌面雪花飄落代碼

    Qt 實現(xiàn)桌面雪花飄落代碼

    這篇文章主要介紹了Qt實現(xiàn)桌面雪花飄落代碼,有需要的朋友可以參考一下
    2013-12-12
  • 通過示例詳解C++智能指針

    通過示例詳解C++智能指針

    這篇文章主要為大家通過示例介紹了C++智能指針的使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • C++ Qt開發(fā)之使用QTcpSocket實現(xiàn)TCP網(wǎng)絡(luò)通信

    C++ Qt開發(fā)之使用QTcpSocket實現(xiàn)TCP網(wǎng)絡(luò)通信

    Qt 是一個跨平臺C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺窗體應(yīng)用程序,本文主要為大家介紹了如何運用QTcpSocket組件實現(xiàn)基于TCP的網(wǎng)絡(luò)通信功能,需要的可以參考下
    2024-03-03
  • Matlab實現(xiàn)四種HSV色輪圖繪制的示例代碼

    Matlab實現(xiàn)四種HSV色輪圖繪制的示例代碼

    色輪圖就是色彩相位圖,它完整表現(xiàn)了色相環(huán)360度的全部顏色。本文將利用Matlab語言繪制四種不同的HSV色輪圖,感興趣的可以動手嘗試一下
    2022-07-07
  • C語言操作符超詳細講解上篇

    C語言操作符超詳細講解上篇

    C?語言提供了豐富的操作符,有:算術(shù)操作符,移位操作符,位操作符,賦值操作符,單目操作符,關(guān)系操作符,邏輯操作符,條件操作符等。因為篇幅過大將分兩篇講解,讓我們通讀本篇來詳細了解吧
    2022-04-04
  • C++中二進制數(shù)據(jù)序列化和反序列化詳解

    C++中二進制數(shù)據(jù)序列化和反序列化詳解

    這篇文章主要為大家詳細介紹了C++中二進制數(shù)據(jù)序列化和反序列化的相關(guān)知識,文中的示例代碼講解詳細,具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解下
    2023-11-11
  • 基于MFC實現(xiàn)自定義復(fù)選框效果

    基于MFC實現(xiàn)自定義復(fù)選框效果

    復(fù)選框是一種可同時選中多項的基礎(chǔ)控件,主要是有兩種明顯的狀態(tài):選中與非選中。本文將通過MFC框架實現(xiàn)自定義復(fù)選框效果,感興趣的可以了解一下
    2022-02-02

最新評論