網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
三種拷貝方式
淺拷貝
對(duì)于自定義的string類(lèi),如果不顯式定義拷貝構(gòu)造函數(shù),編譯器會(huì)默認(rèn)生成拷貝構(gòu)造函數(shù),此時(shí)的拷貝方式是淺拷貝,兩個(gè)對(duì)象會(huì)公用一塊兒內(nèi)存,析構(gòu)時(shí)同一空間被釋放兩次,會(huì)導(dǎo)致程序崩潰。
賦值運(yùn)算符重載也會(huì)產(chǎn)生同樣的問(wèn)題,同時(shí),由于被賦值對(duì)象原來(lái)有空間,淺拷貝還會(huì)導(dǎo)致舊的空間無(wú)法找到,造成內(nèi)存泄漏。
深拷貝
類(lèi)中設(shè)計(jì)到資源的管理,拷貝構(gòu)造函數(shù)、賦值運(yùn)算符重載以及析構(gòu)函數(shù)都要顯示給出,按照深拷貝的方式。
深拷貝的方式讓每個(gè)對(duì)象都獨(dú)立擁有一份資源,不會(huì)造成多次釋放導(dǎo)致程序崩潰的問(wèn)題。
寫(xiě)時(shí)拷貝
寫(xiě)時(shí)拷貝是通過(guò)淺拷貝+引用計(jì)數(shù)的方式來(lái)實(shí)現(xiàn)的,引用計(jì)數(shù)是用來(lái)記錄資源的被引用的次數(shù),
可以將這種寫(xiě)時(shí)拷貝的機(jī)制想象成“拖延癥”,只有當(dāng)不得不進(jìn)行拷貝時(shí),才會(huì)開(kāi)辟新空間進(jìn)行拷貝
VS與GCC中的拷貝方式
Windows VS2022
VS中采用的是深拷貝的方式
Linux GCC
GCC編譯器采用的是寫(xiě)時(shí)拷貝的方式
簡(jiǎn)易string類(lèi)
簡(jiǎn)易string類(lèi)主要實(shí)現(xiàn)四個(gè)功能,即構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、析構(gòu)函數(shù)、賦值運(yùn)算符重載,主要考察深淺拷貝
實(shí)現(xiàn)簡(jiǎn)易string類(lèi)有兩種代碼風(fēng)格,一種傳統(tǒng)版寫(xiě)法,代碼復(fù)用性第,可讀性較好;另一種稱(chēng)為現(xiàn)代版寫(xiě)法,代碼復(fù)用性高,但是較難理解。
傳統(tǒng)版寫(xiě)法的string類(lèi)
構(gòu)造函數(shù)
步驟:
- 判斷是否為空指針,string類(lèi)不允許nullptr構(gòu)造對(duì)象
- 申請(qǐng)新空間
- 將字符串中的值拷貝到申請(qǐng)的空間
string(const char* str = "")
{
if (nullptr == str)
{
assert(false);
return;
}
//+1是因?yàn)橛?\0',strcpy會(huì)將源字符串中的'\0'拷貝到目標(biāo)空間
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
拷貝構(gòu)造函數(shù)
步驟:
- 開(kāi)辟空間
- 用源對(duì)象的_str給當(dāng)前對(duì)象的_str賦值
string(const string& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
賦值運(yùn)算符重載
步驟:
- 判斷是否自己給自己賦值
- 開(kāi)辟新空間
- 拷貝元素
- 刪除舊空間
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;
}
另一種寫(xiě)法
這種寫(xiě)法不用定義臨時(shí)變量,代碼相對(duì)簡(jiǎn)潔一點(diǎn),但是如果new申請(qǐng)空間失敗,舊的空間也無(wú)法找到。
析構(gòu)函數(shù)
步驟:
- 釋放空間
- 將指針置為空
~string()
{
?? ?if (_str)
?? ?{
?? ??? ?delete[]_str;
?? ??? ?_str = nullptr;
?? ?}
}
?
現(xiàn)代版寫(xiě)法string類(lèi)
構(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ù),實(shí)現(xiàn)了代碼的復(fù)用
步驟:
- 在初始化列表中將_str置為空
- 定義一個(gè)臨時(shí)的string類(lèi)對(duì)象,指向要拷貝的對(duì)象相同位置
- 交換臨時(shí)對(duì)象與當(dāng)前對(duì)象的_str
string(const string& s)
:_str(nullptr)
{
//調(diào)用構(gòu)造函數(shù)
string temp(s._str);
//交換以后temp指向空,函數(shù)退出后被銷(xiāo)毀
swap(_str, temp._str);
}
賦值運(yùn)算符重載函數(shù)
步驟:
- 判斷是否為自己給自己賦值
- 調(diào)用拷貝構(gòu)造函數(shù)定義臨時(shí)變量
- 交換臨時(shí)變量與當(dāng)前對(duì)象的_str
string& operator=(string& s)
{
if (this != &s)
{
string temp(s);
swap(_str, s._str);
}
return *this;
}
更簡(jiǎn)潔的寫(xiě)法:
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é)
原文鏈接:https://blog.csdn.net/qq_44631587/article/details/126271106
相關(guān)推薦
- 2022-07-23 .Net創(chuàng)建型設(shè)計(jì)模式之工廠方法模式(Factory?Method)_基礎(chǔ)應(yīng)用
- 2023-04-01 解讀opencv->tensorrt的數(shù)據(jù)排列方式_python
- 2022-05-05 Python實(shí)現(xiàn)蟻群算法_python
- 2022-02-26 C#中XML基礎(chǔ)用法_C#教程
- 2023-07-26 node中的內(nèi)置模塊path和fs
- 2024-03-24 go 連接redis集群
- 2022-03-21 .NET?6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)ActionFilter_實(shí)用技巧
- 2022-04-24 詳解golang?定時(shí)任務(wù)time.Sleep和time.Tick實(shí)現(xiàn)結(jié)果比較_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支