C++深淺拷貝及簡易string類實現(xiàn)方式
三種拷貝方式
淺拷貝
對于自定義的string類,如果不顯式定義拷貝構(gòu)造函數(shù),編譯器會默認生成拷貝構(gòu)造函數(shù),此時的拷貝方式是淺拷貝,兩個對象會公用一塊兒內(nèi)存,析構(gòu)時同一空間被釋放兩次,會導致程序崩潰。

賦值運算符重載也會產(chǎn)生同樣的問題,同時,由于被賦值對象原來有空間,淺拷貝還會導致舊的空間無法找到,造成內(nèi)存泄漏。
深拷貝
類中設計到資源的管理,拷貝構(gòu)造函數(shù)、賦值運算符重載以及析構(gòu)函數(shù)都要顯示給出,按照深拷貝的方式。
深拷貝的方式讓每個對象都獨立擁有一份資源,不會造成多次釋放導致程序崩潰的問題。

寫時拷貝
寫時拷貝是通過淺拷貝+引用計數(shù)的方式來實現(xiàn)的,引用計數(shù)是用來記錄資源的被引用的次數(shù),


可以將這種寫時拷貝的機制想象成“拖延癥”,只有當不得不進行拷貝時,才會開辟新空間進行拷貝
VS與GCC中的拷貝方式
Windows VS2022
VS中采用的是深拷貝的方式

Linux GCC
GCC編譯器采用的是寫時拷貝的方式

簡易string類
簡易string類主要實現(xiàn)四個功能,即構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、析構(gòu)函數(shù)、賦值運算符重載,主要考察深淺拷貝
實現(xiàn)簡易string類有兩種代碼風格,一種傳統(tǒng)版寫法,代碼復用性第,可讀性較好;另一種稱為現(xiàn)代版寫法,代碼復用性高,但是較難理解。
傳統(tǒng)版寫法的string類
構(gòu)造函數(shù)
步驟:
- 判斷是否為空指針,string類不允許nullptr構(gòu)造對象
- 申請新空間
- 將字符串中的值拷貝到申請的空間
string(const char* str = "")
{
if (nullptr == str)
{
assert(false);
return;
}
//+1是因為有'\0',strcpy會將源字符串中的'\0'拷貝到目標空間
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
拷貝構(gòu)造函數(shù)
步驟:
- 開辟空間
- 用源對象的_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* temp = new char[strlen(s._str) + 1];
strcpy(temp, s._str);
delete[] _str;
_str = temp;
}
return *this;
}
另一種寫法

這種寫法不用定義臨時變量,代碼相對簡潔一點,但是如果new申請空間失敗,舊的空間也無法找到。
析構(gòu)函數(shù)
步驟:
- 釋放空間
- 將指針置為空
~string()
{
?? ?if (_str)
?? ?{
?? ??? ?delete[]_str;
?? ??? ?_str = nullptr;
?? ?}
}
現(xiàn)代版寫法string類
構(gòu)造函數(shù)
string(const char* str = "")
{
if (str == nullptr)
{
assert(false);
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)中利用構(gòu)造函數(shù),實現(xiàn)了代碼的復用
步驟:
- 在初始化列表中將_str置為空
- 定義一個臨時的string類對象,指向要拷貝的對象相同位置
- 交換臨時對象與當前對象的_str
string(const string& s)
:_str(nullptr)
{
//調(diào)用構(gòu)造函數(shù)
string temp(s._str);
//交換以后temp指向空,函數(shù)退出后被銷毀
swap(_str, temp._str);
}

賦值運算符重載函數(shù)
步驟:
- 判斷是否為自己給自己賦值
- 調(diào)用拷貝構(gòu)造函數(shù)定義臨時變量
- 交換臨時變量與當前對象的_str
string& operator=(string& s)
{
if (this != &s)
{
string temp(s);
swap(_str, s._str);
}
return *this;
}
更簡潔的寫法:
string& operator=(string s)
{
//傳參調(diào)用拷貝構(gòu)造函數(shù),不用判斷是否給自己賦值
swap(_str, s._str);
return *this;
}
析構(gòu)函數(shù)
~string()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
C語言實現(xiàn)無規(guī)律數(shù)據(jù)加密、解密功能
這篇文章主要為大家詳細介紹了C語言實現(xiàn)無規(guī)律數(shù)據(jù)加密、解密功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-03-03

