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

掌握C++:揭秘寫時(shí)拷貝與淺深拷貝之間的關(guān)系

 更新時(shí)間:2024年01月30日 09:01:17   作者:字節(jié)連結(jié)  
探索C++的奧秘,本指南將揭秘寫時(shí)拷貝與淺深拷貝之間的微妙關(guān)系,摸索這些復(fù)雜概念背后的邏輯,讓你的編程技能瞬間提升,來(lái)吧,讓我們一起進(jìn)入這個(gè)引人入勝的C++世界!

1. 經(jīng)典的string類問題

上一篇博客已經(jīng)對(duì)string類進(jìn)行了簡(jiǎn)單的介紹,大家只要能夠正常使用即可。

在面試中,面試官總喜歡讓學(xué)生自己來(lái)模擬實(shí)現(xiàn)string類,最主要是實(shí)現(xiàn)string類的構(gòu)造、拷貝構(gòu)造、賦值運(yùn)算符重載以及析構(gòu)函數(shù)。大家看下以下string類的實(shí)現(xiàn)是否有問題?

// 為了和標(biāo)準(zhǔn)庫(kù)區(qū)分,此處使用String
class String
{
public:
	//String()
	//	:_str(new char[1])
	//{
	//	*_str = '\0';
	//}
	
	//String(const char* str = "\0")	// 錯(cuò)誤示范
	//String(const char* str = nullptr)	// 錯(cuò)誤示范
	String(const char* str = "")
	{
		// 構(gòu)造String類對(duì)象時(shí),如果傳遞nullptr指針,可以認(rèn)為程序非法
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	
private:
	char* _str;
};

// 測(cè)試
void TestString()
{
	String s1("hello string");
	String s2(s1);
}

在這里插入圖片描述

說(shuō)明:上述String類沒有顯式定義其拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載,此時(shí)編譯器會(huì)合成默認(rèn)的,當(dāng)用s1構(gòu)造s2時(shí),編譯器會(huì)調(diào)用默認(rèn)的拷貝構(gòu)造。最終導(dǎo)致的問題時(shí),s1、s2共用同一塊內(nèi)存空間,在釋放時(shí)同一塊空間被釋放多次而引起程序崩潰,這種拷貝方式,稱為淺拷貝。

2. 淺拷貝

淺拷貝:也稱位拷貝,編譯器只是將對(duì)象中的值拷貝過(guò)來(lái)。如果對(duì)象中管理資源,最后就會(huì)導(dǎo)致多個(gè)對(duì)象共享同一份資源,當(dāng)一個(gè)對(duì)象銷毀時(shí)就會(huì)將該資源釋放掉,而此時(shí)另一些對(duì)象不知道該資源已經(jīng)被釋放,以為還有效,所以當(dāng)繼續(xù)對(duì)資源進(jìn)行操作時(shí),就會(huì)發(fā)生訪問違規(guī)。

就像一個(gè)家庭中有兩個(gè)孩子,但父母只買了一份玩具,兩個(gè)孩子愿意一塊玩,則萬(wàn)事大吉,萬(wàn)一不想分享就你爭(zhēng)我奪,玩具損壞。


在這里插入圖片描述

可以采用深拷貝解決淺拷貝問題,即:每個(gè)對(duì)象都有一份獨(dú)立的資源,不要和其他對(duì)象共享。父母給每個(gè)孩子都買一份玩具,各自玩各自的就不會(huì)有問題了。


在這里插入圖片描述

3. 深拷貝

如果一個(gè)類中涉及到資源的管理,其拷貝構(gòu)造函數(shù),賦值運(yùn)算符重載以及析構(gòu)函數(shù)必須要顯式給出。一般情況都是按照深拷貝方式提供。
在這里插入圖片描述

3.1 傳統(tǒng)寫法的String類

class String
{
public:
	String(const char* str = "")
	{
		// 構(gòu)造String類對(duì)象時(shí),如果傳遞nullptr指針,可以認(rèn)為程序非法
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	
	String(const String& s)
		: _str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}
	
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			char* pStr = new char[strlen(s._str) + 1];
			strcpy(pStr, s._str);
			delete[] _str;
			_str = pStr;
		}
		return *this;
	}
	
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	
private:
	char* _str;
};

3.2 現(xiàn)代寫法的String類

class String
{
public:
	String(const char* str = "")
	{
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	
	String(const String& s)
		: _str(nullptr)
	{
		String strTmp(s._str);
		swap(_str, strTmp._str);
	}
	
	// 對(duì)比下和上面的賦值那個(gè)實(shí)現(xiàn)比較好?
	String& operator=(String s)
	{
		swap(_str, s._str);
		return *this;
	}
	
	//String& operator=(const String& s)
	//{
	//	if (this != &s)
	//	{
	//		String strTmp(s);
	//		swap(_str, strTmp._str);
	//	}
	//	return *this;
	//}

	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	
private:
	char* _str;
};

傳統(tǒng)寫法就是老老實(shí)實(shí)自己開空間、自己拷貝數(shù)據(jù)、自己刪除舊空間;而現(xiàn)代寫法則利用了swap()函數(shù)以及局部變量出作用域自動(dòng)銷毀的特性,讓函數(shù)和編譯器幫我們“打工”,我們只要坐享其成即可。這兩種方式在效率上并沒有什么區(qū)別,只是讓代碼看起來(lái)更簡(jiǎn)潔,但這又會(huì)使代碼的可讀性降低??傮w來(lái)說(shuō),我還是更偏向于傳統(tǒng)寫法。

4. 寫時(shí)拷貝

在這里插入圖片描述

寫時(shí)拷貝就是一種拖延癥,是在淺拷貝的基礎(chǔ)之上增加了引用計(jì)數(shù)的方式來(lái)實(shí)現(xiàn)的。

引用計(jì)數(shù):用來(lái)記錄資源使用者的個(gè)數(shù)。在構(gòu)造時(shí),將資源的計(jì)數(shù)給成1,每增加一個(gè)對(duì)象使用該資源,就給計(jì)數(shù)增加1,當(dāng)某個(gè)對(duì)象被銷毀時(shí),先給該計(jì)數(shù)-1,然后再檢查是否需要釋放資源,如果計(jì)數(shù)為1,說(shuō)明該對(duì)象是資源的最后一個(gè)使用者,將該資源釋放;否則就不能釋放,因?yàn)檫€有其他對(duì)象也在使用該資源。

到此這篇關(guān)于掌握C++:揭秘寫時(shí)拷貝與淺深拷貝之間的關(guān)系的文章就介紹到這了,更多相關(guān)C++ 淺拷貝 深拷貝 寫時(shí)拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++哈希應(yīng)用之位圖,哈希切分與布隆過(guò)濾器詳解

    C++哈希應(yīng)用之位圖,哈希切分與布隆過(guò)濾器詳解

    這篇文章主要為大家詳細(xì)介紹了C++哈希應(yīng)用中的位圖、哈希切分與布隆過(guò)濾器,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下
    2023-04-04
  • C語(yǔ)言關(guān)于自定義數(shù)據(jù)類型之枚舉和聯(lián)合體詳解

    C語(yǔ)言關(guān)于自定義數(shù)據(jù)類型之枚舉和聯(lián)合體詳解

    枚舉顧名思義就是把所有的可能性列舉出來(lái),像一個(gè)星期分為七天我們就可以使用枚舉,聯(lián)合體是由關(guān)鍵字union和標(biāo)簽定義的,和枚舉是一樣的定義方式,不一樣的是,一個(gè)聯(lián)合體只有一塊內(nèi)存空間,什么意思呢,就相當(dāng)于只開辟最大的變量的內(nèi)存,其他的變量都在那個(gè)變量占據(jù)空間
    2021-11-11
  • 詳解C++ 共享數(shù)據(jù)保護(hù)機(jī)制

    詳解C++ 共享數(shù)據(jù)保護(hù)機(jī)制

    這篇文章主要介紹了詳解C++ 共享數(shù)據(jù)保護(hù)機(jī)制的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下
    2021-02-02
  • 在C語(yǔ)言里單引號(hào)和雙引號(hào)的區(qū)別

    在C語(yǔ)言里單引號(hào)和雙引號(hào)的區(qū)別

    這篇文章主要介紹了在C語(yǔ)言里單引號(hào)和雙引號(hào)的區(qū)別,本文通過(guò)代碼的實(shí)例和注釋的詳細(xì)的說(shuō)明了單引號(hào)和雙引號(hào)的概念與區(qū)別,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++實(shí)現(xiàn)LeetCode(16.最近三數(shù)之和)

    C++實(shí)現(xiàn)LeetCode(16.最近三數(shù)之和)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(16.最近三數(shù)之和),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 一篇文章徹底搞懂C++常見容器

    一篇文章徹底搞懂C++常見容器

    容器就是一些特定類型對(duì)象的集合,容器可以分為順序容器和關(guān)聯(lián)容器,下面這篇文章主要給大家介紹了關(guān)于C++常見容器的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • 你知道C語(yǔ)言中#和##表示的意義嗎

    你知道C語(yǔ)言中#和##表示的意義嗎

    如標(biāo)題,這篇文章會(huì)講解C語(yǔ)言中的#和##是啥意思。我相信,大部分朋友應(yīng)該都沒怎么用過(guò),這兩個(gè)玩意的使用條件也相當(dāng)苛刻,快跟隨小編一起來(lái)看看吧
    2023-04-04
  • C語(yǔ)言嵌入informix基礎(chǔ)入門示例講解

    C語(yǔ)言嵌入informix基礎(chǔ)入門示例講解

    這篇文章主要介紹了C語(yǔ)言嵌入informix基礎(chǔ)方法,大家參考使用
    2013-11-11
  • C語(yǔ)言算法練習(xí)之?dāng)?shù)組元素排序

    C語(yǔ)言算法練習(xí)之?dāng)?shù)組元素排序

    這篇文章主要為大家介紹了C語(yǔ)言算法練習(xí)中數(shù)組元素排序的實(shí)現(xiàn)方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,需要的可以參考一下
    2022-09-09
  • C++ 重載與重寫的區(qū)別與實(shí)現(xiàn)

    C++ 重載與重寫的區(qū)別與實(shí)現(xiàn)

    在面向?qū)ο笳Z(yǔ)言中,經(jīng)常提到重載與重寫,本文主要介紹了C++ 重載與重寫的區(qū)別與實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01

最新評(píng)論