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

C++超詳細講解拷貝構造函數(shù)

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

構造函數(shù)

只有單個形參,該形參是對本類類型對象的引用(一般常用const修飾),在用已存在的類類型對象創(chuàng)建新對象時由編譯器自動調用

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

特征

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

特征如下:

  • 拷貝構造是構造函數(shù)的一個重載;
  • 拷貝構造的參數(shù)只有一個并且類型必須是該類的引用,而不是使用傳值調用,否則會無限遞歸;
  • 若沒有顯式定義拷貝構造函數(shù),編譯器會自己生成一個默認拷貝構造,默認的拷貝構造函數(shù)對象按按內存存儲和字節(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

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

通過圖示說明:

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

下面這個程序會崩潰

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;
}

原因是兩個string類的成員指針都指向一塊內存,而它們又分別調用了一次析構函數(shù),相當于對同一塊內存空間釋放了兩次,程序崩潰。

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

編譯器生成的拷貝構造

編譯器默認生成的拷貝構造會做些什么呢?

  • 對于內置類型成員

? 完成值拷貝;

  • 對于自定義類型成員

調用成員的拷貝構造;

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;
}

如果默認生成的拷貝構造沒有調用Time類成員的拷貝構造,那么d2的_t的值應該是(_hour = 0, _minute = 0, _second = 0),而這里最終的結果是d2中的_t和d2中的_t值相同。

這里Date類中自動生成的拷貝構造函數(shù)的內置類型會進行字節(jié)序拷貝,而對于自定義類型_t調用了Time的拷貝構造函數(shù)。

拷貝構造的初始化列表

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

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

  • 成員變量沒有指針;
  • 成員有指針,但并沒有管理內存資源;

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

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

我們都知道,編譯器生成的構造函數(shù)在初始化列表會調用成員的構造函數(shù),而我們顯式去定義構造函數(shù)時,即使我們不寫也會在初始化列表去調用自定義類型成員的構造函數(shù)。

通過類比,我就犯了一個低級錯誤:

就是既然編譯器生成的拷貝構造可以在初始化列表自動調用自定義成員的拷貝構造,那么我們顯式定義的拷貝構造即使不寫,也會在初始化列表自動去調用自定義成員的拷貝構造。

于是我寫出了如下代碼:

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)//顯式定義了拷貝構造
	{
	}
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;
}

通過監(jiān)視窗口查看d2調用拷貝構造后的值:

并沒有拷貝成功。

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

結論

拷貝構造函數(shù)是構造函數(shù)的一種,它也有初始化列表,如果是編譯器生成的拷貝構造,它會對內置類型做字節(jié)序拷貝,對自定義類型成員會調用自定義成員的拷貝構造。

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

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

相關文章

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

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

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

    C語言完整特性詳情

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

    解析C++浮點數(shù)無效值的定義與無效值判定的小結

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

    C語言實現(xiàn)中綴表達式轉換為后綴表達式

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

    C++內存管理詳細解析

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

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

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

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

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

    基于Qt制作一個定時關機的小程序

    這篇文章主要為大家詳細介紹了如何基于Qt制作一個有趣的定時關機的小程序,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-12-12
  • 淺談C++為什么非要引入那幾種類型轉換

    淺談C++為什么非要引入那幾種類型轉換

    這篇文章主要介紹了C++為什么非要引入那幾種類型轉換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • C語言排序之?堆排序

    C語言排序之?堆排序

    這篇文章主要介紹了C語言排序之堆排序,文章基于C語言的相關資料展開詳細內容,具有一定的參考資料,需要的小伙伴可以參考一下
    2022-04-04

最新評論

广丰县| 鄂温| 兖州市| 沈丘县| 黎平县| 沙雅县| 布拖县| 大姚县| 赫章县| 深泽县| 常熟市| 武川县| 北海市| 金塔县| 义乌市| 苏尼特左旗| 闻喜县| 额尔古纳市| 增城市| 建阳市| 黔西县| 盱眙县| 乌兰县| 潮安县| 玉环县| 洪江市| 云梦县| 赤城县| 洛扎县| 蒙阴县| 托里县| 永安市| 峨山| 开江县| 定远县| 崇礼县| 天长市| 聂拉木县| 周至县| 秀山| 东乡县|