日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++的深淺拷貝和寫時拷貝你了解嗎_C 語言

作者:林慢慢腦瓜子嗡嗡的 ? 更新時間: 2022-05-26 編程語言

1.淺拷貝

淺拷貝:對于有申請空間的對象的類來說,是按照字節序依次拷貝過去的,并沒有另外申請一塊空間。因此,在調用析構函數的時候會造成同一塊空間釋放兩次的情況,從而使程序崩潰。

如下實例:

class string
{
public:
	string(const char* str)
	{
		//構造string類對象時,如果傳遞nullptr指針
		//認為程序非法,此處斷言下
		assert(str);
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	~string()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
private:
	char* _str;
};
void test()
{
	string s1("linmanman");
	string s2(s1);
}

運行看看,報錯了

image-20211119153738386

分析錯因:

image-20211119155522526

image-20211119160321325

淺拷貝是指向同一塊空間的,這樣就會有倆個無法避免的問題:

1.析構倆次空間,程序崩潰

2.其中一個的值被修改了,會影響到另外一個的值。

深拷貝:給每個對象單獨分配資源,就是給待拷貝的對象另開一片空間,再把原對象空間上的值拷貝過來,這樣在調用析構函數的時候就不會產生沖突。

image-20220213125937937

image-20211119160705278

2.深拷貝

傳統寫法的string類的深拷貝是自己開空間,自己將拷貝的對象拷貝到待拷貝對象中。

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類的深拷貝堪稱是“移花接木”

string(const string& s)
	:_str(nullptr)//必須置空,因為_str開始是個隨機數,交換給tmp._str后,釋放會引起問題
{
	string tmp(s._str);//直接利用構造函數,給tmp對象開辟了一塊空間
	swap(tmp);
}
string& operator=(string s)
{
	swap(s);//這個swap是咱們自己寫的哦
	return *this;
}

順帶提一嘴,各個編譯器深拷貝的底層實現略有差異(當然邏輯是一樣的)

VS 2013下的深拷貝

image-20220213130133785

g++下的深拷貝

image-20220213130200116

3.引用計數+寫時拷貝

寫時拷貝就是一種拖延癥, 是在淺拷貝的基礎之上增加了引用計數的方式來實現的。

引用計數:用來記錄資源使用者的個數。在構造時,將資源的計數給成1,每增加一個對象使用該資源,就給計數增加1,當某個對象被銷毀時,先給該計數減1,然后再檢查是否需要釋放資源,如果計數為1,說明該對象時資源的最后一個使用者, 將該資源釋放;否則就不能釋放,因為還有其他對象在使用該資源。

image-20220213130242526

總結

原文鏈接:https://blog.csdn.net/weixin_48953972/article/details/123566160

欄目分類
最近更新