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

C++中Copy-Swap實(shí)現(xiàn)拷貝交換

 更新時(shí)間:2023年07月09日 15:40:23   作者:Zijian/TENG  
本文主要介紹了C++中Copy-Swap實(shí)現(xiàn)拷貝交換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

正式介紹 Copy-Swap 之前,先看下《劍指 Offer》里的第??題:

如下為類型 CMyString 的聲明,請(qǐng)為該類型添加賦值運(yùn)算符函數(shù)。

class CMyString {
public:
  CMyString(char* pData = nullptr);
  CMyString(const CMyString& str);
  ~CMyString();
private:
  char* m_pData;
};

這道題目雖然基礎(chǔ),但考察點(diǎn)頗多,有區(qū)分度:

  • 返回值類型應(yīng)為引用類型,否則將無(wú)法支持形如 s3 = s2 = s1 的連續(xù)賦值
  • 形參類型應(yīng)為 const 引用類型
  • 無(wú)資源泄露,正確釋放賦值運(yùn)算符左側(cè)的對(duì)象的資源
  • 自賦值安全,能夠正確處理 s1 = s1 的語(yǔ)句
  • 考慮異常安全

解法 1

CMyString& operator=(const CMyString& str)
{
    if(this == &str)
        return *this;
    delete[] m_pData;
    m_pData = nullptr;
    m_pData = new char[strlen(str.m_pData) + 1];
    strcpy(m_pData, str.m_pData);
    return *this;
}

上面代碼有些細(xì)節(jié)需要注意:

  • 刪除數(shù)組使用 delete[] 運(yùn)算符
  • strlen 計(jì)算長(zhǎng)度不含字符串末尾的結(jié)束符 \0
  • strcpy 會(huì)拷貝結(jié)束符 \0

解法 1 滿足考察點(diǎn)中除異常安全外的所有要求:new 的時(shí)候可能由于內(nèi)存不足拋異常,但此時(shí)賦值運(yùn)算符左側(cè)的的對(duì)象已被釋放,m_pData 為空指針,導(dǎo)致左側(cè)對(duì)象處于無(wú)效狀態(tài)。

解決方案:只要先 new 分配空間,再 delete 釋放原來(lái)的空間即可。這樣可以保證即使 new 失敗拋異常,賦值運(yùn)算符左側(cè)對(duì)象也尚未修改,仍處于有效狀態(tài)。

解法 2

《劍指 Offer》中給出了更好的解法:先創(chuàng)建賦值運(yùn)算符右側(cè)對(duì)象的一個(gè)臨時(shí)副本,然后交換賦值運(yùn)算符左側(cè)對(duì)象和該臨時(shí)副本的 m_pData,當(dāng)臨時(shí)對(duì)象 strTemp 離開(kāi)作用域時(shí),自動(dòng)調(diào)用其析構(gòu)函數(shù),釋放 m_pData 指向的資源(即賦值運(yùn)算符左側(cè)對(duì)象原來(lái)的內(nèi)存):

CMyString& operator=(const CMyStirng& str)
{
    if(this != &str)
    {
        CMyString strTemp(str);
        char* pTemp = m_pData;
        m_pData = strTemp.m_pData;
        strTemp.m_pData = pTemp;
    }
    return *this;
}

解法 2 巧妙地利用了類原本的拷貝構(gòu)造、析構(gòu)函數(shù)自動(dòng)進(jìn)行資源管理,同時(shí)又不涉及底層的 new[]/delete[] 操作,可讀性更強(qiáng),也不容易出錯(cuò)。

解法 2 是 Copy-Swap 的雛形。C++ 中管理資源類通常會(huì)定義自己的 swap 函數(shù),與其他拷貝控制成員(拷貝/移動(dòng)構(gòu)造、拷貝/移動(dòng)賦值運(yùn)算符、析構(gòu))不同,swap 不是必須,但卻是重要的優(yōu)化手段,以下是使用 Copy-Swap 慣用法的解法:

解法 3

class CMyString {
    friend void Swap(CMyString& lhs, CMyString& rhs) noexcept
    {
        // 對(duì) CMyString 的成員逐一交換
        std::swap(lhs.m_pData, rhs.m_pData);
    }
    // ...
};
CMyString(CMyString&& str) : CMyString()
{
    Swap(*this, str);
}
CMyString& operator=(CMyStirng str)
{
    Swap(*this, str);
    return *this;
}

這里有幾點(diǎn)需要注意:

  • 拷貝賦值運(yùn)算符的形參類型不再是 const 引用,因?yàn)?Copy-Swap 需要先對(duì)賦值運(yùn)算符右側(cè)對(duì)象進(jìn)行拷貝,這里直接使用值傳遞。這樣一來(lái),也使得 Copy-Swap 天然地異常安全、自賦值安全。
    • 異常安全:進(jìn)入函數(shù) operator=() 之前,先進(jìn)行拷貝
    • 自賦值安全:形參是一個(gè)新創(chuàng)建的臨時(shí)對(duì)象,永遠(yuǎn)不可能是對(duì)象自身
  • 不需要額外實(shí)現(xiàn)移動(dòng)賦值運(yùn)算符:如果賦值運(yùn)算符右側(cè)是一個(gè)右值,則自動(dòng)調(diào)用 CMyString 的移動(dòng)構(gòu)造來(lái)構(gòu)造形參

這還沒(méi)完...

標(biāo)準(zhǔn)庫(kù) std::swap 及 ADL

C++ 標(biāo)準(zhǔn)庫(kù)也提供了 swap 函數(shù),理論上需要一次拷貝,兩次賦值:

void swap(CMyString& lhs, CMyString& rhs)
{
    CMyString tmp(lhs);
    lhs = rhs;
    rhs = tmp;
}

其中 CMyString tmp(lhs) 會(huì)調(diào)用 CMyString 的拷貝構(gòu)造進(jìn)行深拷貝,效率上不如 CMyString 類自己實(shí)現(xiàn)的直接交換指針的效率高。

在進(jìn)行 swap(v1, v2) 的調(diào)用時(shí),如果類實(shí)現(xiàn)了自己的 swap 版本,其匹配程度優(yōu)于標(biāo)準(zhǔn)庫(kù)的版本。如果類沒(méi)有定義自己的 swap,則使用標(biāo)準(zhǔn)庫(kù)的 swap。這種查找匹配方式被稱為 ADL(Argument-Dependent Lookup)。

注意不能使用 std::swap 形式,因?yàn)檫@樣會(huì)強(qiáng)制使用標(biāo)準(zhǔn)庫(kù)的 swap。正確的做法是提前使用 using std::swap 聲明,而后續(xù)所有的 swap 都應(yīng)該是不加限制的(這一點(diǎn)剛好和 std::move 相反):

void swap(Bar& lhs, Bar& rhs)
{
    using std::swap;
    swap(lhs.m1, rhs.m1);
    swap(lhs.m2, rhs.m2);
    swap(lhs.m3, rhs.m3);
}

最終的結(jié)果

class CMyString {
    friend void swap(CMyString& lhs, CMyString& rhs) noexcept
    {
        // 對(duì) CMyString 的成員逐一交換
        using std::swap;
        swap(lhs.m_pData, rhs.m_pData);
    }
    // ...
};
CMyString(CMyString&& str) : CMyString()
{
    swap(*this, str);
}
CMyString& operator=(CMyStirng str)
{
    swap(*this, str);
    return *this;
}

到此這篇關(guān)于C++中Copy-Swap實(shí)現(xiàn)拷貝交換的文章就介紹到這了,更多相關(guān)C++ Copy-Swap拷貝交換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • C++單鏈表實(shí)現(xiàn)大數(shù)加法

    C++單鏈表實(shí)現(xiàn)大數(shù)加法

    這篇文章主要為大家詳細(xì)介紹了C++單鏈表實(shí)現(xiàn)大數(shù)加法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Qt各版本對(duì)C++標(biāo)準(zhǔn)的支持情況

    Qt各版本對(duì)C++標(biāo)準(zhǔn)的支持情況

    本文主要介紹了Qt各版本對(duì)C++標(biāo)準(zhǔn)的支持情況,文中通過(guò)表格介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-06-06
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C語(yǔ)言鄰接表建立圖詳解

    C語(yǔ)言鄰接表建立圖詳解

    這篇文章主要介紹了C語(yǔ)言鄰接表建立圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • C++中CopyFile和MoveFile函數(shù)使用區(qū)別的示例分析

    C++中CopyFile和MoveFile函數(shù)使用區(qū)別的示例分析

    這篇文章主要介紹了C++中CopyFile和MoveFile函數(shù)使用區(qū)別的示例分析,CopyFile表示將文件A拷貝到B,如果B已經(jīng)存在則覆蓋,MoveFile表示將文件A移動(dòng)到。對(duì)此感興趣的可以來(lái)了解一下
    2020-07-07
  • C++ deque容器的用法詳解

    C++ deque容器的用法詳解

    在處理一些數(shù)組的事情,所以隨手保留一下Deque容器的使用方法很有必要,接下來(lái)通過(guò)本文給大家重點(diǎn)介紹C++ deque容器的用法及deque和vector的區(qū)別講解,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Qt qml實(shí)現(xiàn)動(dòng)態(tài)輪播圖效果

    Qt qml實(shí)現(xiàn)動(dòng)態(tài)輪播圖效果

    這篇文章主要為大家詳細(xì)介紹了Qt和qml實(shí)現(xiàn)動(dòng)態(tài)輪播圖效果的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2024-12-12
  • C++ 配置文件管理神器 yaml-cpp 實(shí)戰(zhàn)指南

    C++ 配置文件管理神器 yaml-cpp 實(shí)戰(zhàn)指南

    本文主要介紹了C++ 配置文件管理神器 yaml-cpp 實(shí)戰(zhàn)指南,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-05-05
  • 淺析C++可變參數(shù)模板的展開(kāi)方式

    淺析C++可變參數(shù)模板的展開(kāi)方式

    可變參數(shù)模板(variadic templates)是C++11新增的強(qiáng)大的特性之一,它對(duì)模板參數(shù)進(jìn)行了高度泛化,能表示0到任意個(gè)數(shù)、任意類型的參數(shù),這篇文章主要介紹了C++可變參數(shù)模板的展開(kāi)方式,需要的朋友可以參考下
    2022-04-04
  • VC通過(guò)托盤圖標(biāo)得到該所屬進(jìn)程的實(shí)現(xiàn)代碼

    VC通過(guò)托盤圖標(biāo)得到該所屬進(jìn)程的實(shí)現(xiàn)代碼

    這篇文章主要介紹了VC通過(guò)托盤圖標(biāo)得到該所屬進(jìn)程的實(shí)現(xiàn)代碼,為了方便大家使用特將多個(gè)代碼分享給大家,需要的朋友可以參考下
    2021-10-10

最新評(píng)論

星子县| 墨江| 吐鲁番市| 天镇县| 平凉市| 清河县| 老河口市| 东光县| 东光县| 涿州市| 楚雄市| 大渡口区| 黑水县| 邓州市| 灵石县| 长葛市| 湖北省| 寻甸| 浙江省| 双柏县| 松江区| 乃东县| 博乐市| 泸水县| 南郑县| 中宁县| 高阳县| 和龙市| 习水县| 陆河县| 雷山县| 吉木乃县| 平泉县| 延长县| 河池市| 鲁山县| 肥东县| 宁都县| 延吉市| 宁化县| 永川市|