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

詳解C++中移動(dòng)語(yǔ)義的概念與使用

 更新時(shí)間:2023年06月09日 08:42:24   作者:ENG八戒  
本篇文章主要為大家詳細(xì)介紹了C++中移動(dòng)語(yǔ)義的相關(guān)知識(shí),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧

過(guò)去寫(xiě) C/C++ 代碼,大家對(duì)數(shù)據(jù)做傳遞時(shí),都習(xí)慣先拷貝再賦值。比如,把數(shù)據(jù)從 t1 復(fù)制到 t2,復(fù)制完成后 t2 和 t1 的狀態(tài)是一致的,t1 狀態(tài)沒(méi)變。這里的狀態(tài)指的是對(duì)象內(nèi)部的非靜態(tài)成員數(shù)據(jù)集合。

在程序運(yùn)行過(guò)程中,復(fù)制過(guò)程既要分配空間又要拷貝內(nèi)容,對(duì)于空間和時(shí)間都是種損耗。復(fù)制操作,無(wú)疑是一門(mén)很大的開(kāi)銷(xiāo),何況經(jīng)常觸發(fā)資源復(fù)制的時(shí)候。

來(lái)看看普通的函數(shù)返回值到底有哪些開(kāi)銷(xiāo),

std::string getString()
{
    std::string s;
    // ...

    return s;
}

int main()
{
    std::string str = getString();
    // ...
}

假設(shè)你的編譯器還不支持 C++ 11,那么,在 main() 函數(shù)里調(diào)用 getString() 時(shí),需要在調(diào)用棧里分配臨時(shí)對(duì)象用于復(fù)制 getString() 的返回值 s,復(fù)制完成調(diào)用 s 的析構(gòu)函數(shù)釋放對(duì)象。然后,再調(diào)用 std::string 類(lèi)的復(fù)制賦值運(yùn)算符函數(shù)將臨時(shí)對(duì)象復(fù)制到 str,同時(shí)調(diào)用臨時(shí)對(duì)象的析構(gòu)函數(shù)執(zhí)行釋放。

那么,有沒(méi)有技巧可以實(shí)現(xiàn)上面示例代碼同樣的效果,同時(shí)避免復(fù)制?

有的,就是接下來(lái)重點(diǎn)介紹的移動(dòng)(和中國(guó)移動(dòng)無(wú)關(guān))。

相對(duì)于復(fù)制,移動(dòng)無(wú)須重新分配空間和拷貝內(nèi)容,只需把源對(duì)象的數(shù)據(jù)重新分配給目標(biāo)對(duì)象即可。移動(dòng)后目標(biāo)對(duì)象狀態(tài)與移動(dòng)前的源對(duì)象狀態(tài)一致,但是移動(dòng)后源對(duì)象狀態(tài)被清空。

實(shí)際上,大部份的情況下,數(shù)據(jù)僅僅需要移動(dòng)即可,拷貝復(fù)制顯得多余。就像,你從圖書(shū)館借書(shū),把自己手機(jī)的 SIM 卡拔出來(lái)再插到其它手機(jī)上,去商店買(mǎi)東西你的錢(qián)從口袋移動(dòng)到收銀柜等等。

那么,是不是可以對(duì)所有的數(shù)據(jù)都執(zhí)行移動(dòng)?

答案是否定的。在現(xiàn)代 C++ 中,只有右值可以被移動(dòng)。

左右值概念

在 C++ 11 之前,左右值的劃分比較簡(jiǎn)單,只有左值和右值兩種。

但是從 C++ 11 開(kāi)始,重新把值類(lèi)別劃分成了五種,左值(lvalue, left value),將亡值(xvalue, expiring value),純右值(prvalue, pure right value),泛左值(glvalue, generalized left value),右值(rvalue, right value)。不過(guò)后邊的兩種 glvalue 和 rvalue 是基于前面的三種組合而成。從集合概念來(lái)看,glvalue 包含 lvalue 和 xvalue,rvalue 包含 xvalue 和 prvalue。

左右值劃分的依據(jù)是:具名和可被移動(dòng)。

具名,簡(jiǎn)單點(diǎn)理解就是尋址??杀灰苿?dòng),允許對(duì)量的內(nèi)部資源移動(dòng)到其它位置,并且保持量自身是有效的,但是狀態(tài)不確定。

  • lvalue:具名且不可移動(dòng)
  • xvalue:具名且可移動(dòng)
  • prvalue:不具名且可移動(dòng)

那么,可以看到泛左值(glvalue)其實(shí)就是具名的量,右值就是可移動(dòng)的量。

以往在往函數(shù)傳參的時(shí)候,經(jīng)常有用到值引用的模式,形式如下:

function(T& obj)

T 是類(lèi)型,obj 是參數(shù)。

到了現(xiàn)代 C++,原來(lái)的值引用就變成了左值引用,另外還出現(xiàn)了右值引用,形式如下:

function(T&& obj)

那么 C++ 11 是怎樣實(shí)現(xiàn)移動(dòng)操作的呢?

實(shí)現(xiàn)移動(dòng)操作

移動(dòng)操作依賴(lài)于類(lèi)內(nèi)部特殊成員函數(shù)的執(zhí)行,但前提是該對(duì)象是可移動(dòng)的。如果恰好對(duì)象是左值(lvalue)呢?

C++ 11 的標(biāo)準(zhǔn)庫(kù)就提供了 std::move() 實(shí)現(xiàn)左右值轉(zhuǎn)換操作。std::move() 用于將表達(dá)式從 lvalue(左值) 轉(zhuǎn)換成 xvalue(將亡值),但不會(huì)對(duì)數(shù)值執(zhí)行移動(dòng)。當(dāng)然,使用強(qiáng)制類(lèi)型轉(zhuǎn)換也是可以達(dá)到同樣目的。

std::move(obj); // 等價(jià)于 static_cast<T&&>(obj);

在 stack overflow 上看到對(duì) std::move() 的一段描述,與其說(shuō)它是一個(gè)函數(shù),不如說(shuō),它是編譯器對(duì)表達(dá)式值評(píng)估的方式轉(zhuǎn)換器。

以往慣常使用 C++ 類(lèi)定義時(shí),我們都知道有這么幾個(gè)特殊的成員函數(shù):

  • 默認(rèn)構(gòu)造函數(shù)(default constructor)
  • 復(fù)制構(gòu)造函數(shù)(copy constructor)
  • 復(fù)制賦值運(yùn)算符函數(shù)(copy assignment operator)
  • 析構(gòu)函數(shù)(destructor)

來(lái)看看一個(gè)簡(jiǎn)單的例子:

class MB // MemoryBlock
{
public:
    // 為下面代碼演示簡(jiǎn)單起見(jiàn)
    // 在 public 定義成員屬性
    size_t size;
    char *buf;

    // 默認(rèn)構(gòu)造函數(shù)
    explicit MB(int sz = 1024)
        : size(sz), buf(new char[sz]) {}
    // 析構(gòu)函數(shù)
    ~MB() {
        if (buf != nullptr) {
            delete[] buf;
        }
    }
    // 復(fù)制構(gòu)造函數(shù)
    MB(const MB& obj)
        : size(obj.size),
          buf(new char[obj.size]) {
        memcpy(buf, obj.buf, size);
    }
    // 復(fù)制賦值運(yùn)算符函數(shù)
    MB& operator=(const MB& obj) {
        if (this != &obj) {
            if (buf != nullptr) {
                delete[] buf;
            }
            size = obj.size;
            buf = new char[size]; 
            memcpy(buf, obj.buf, size);
        }
        return *this;
    }
}

為了支持移動(dòng)操作,從 C++ 11 開(kāi)始,類(lèi)定義里新增了兩個(gè)特殊成員函數(shù):

  • 移動(dòng)構(gòu)造函數(shù)(move constructor)
  • 移動(dòng)賦值運(yùn)算符函數(shù)(move assignment operator)

移動(dòng)構(gòu)造函數(shù)

在構(gòu)造新對(duì)象時(shí),如果傳入的參數(shù)是右值引用對(duì)象,就會(huì)調(diào)用移動(dòng)構(gòu)造函數(shù)創(chuàng)建對(duì)象。如果沒(méi)有自定義移動(dòng)構(gòu)造函數(shù),那么編譯器就會(huì)自動(dòng)生成,默認(rèn)實(shí)現(xiàn)是遍歷調(diào)用成員屬性的移動(dòng)構(gòu)造函數(shù),并移動(dòng)右值對(duì)象的成員屬性數(shù)據(jù)到新對(duì)象。

定義一般聲明形式如下:

T::T(C&& other);

基于上面的簡(jiǎn)單例子:

class MB // MemoryBlock
{
public:
    // ...

    // 移動(dòng)構(gòu)造函數(shù)
    MB(MB&& obj)
        : size(0), buf(nullptr) {
        // 移動(dòng)源對(duì)象數(shù)據(jù)到新對(duì)象
        size = obj.size;
        buf = obj.buf;
        // 清空源對(duì)象狀態(tài)
        // 避免析構(gòu)函數(shù)多次釋放資源
        obj.size = 0;
        obj.buf = nullptr;
    }
}

可見(jiàn),移動(dòng)構(gòu)造函數(shù)的執(zhí)行過(guò)程,僅僅是簡(jiǎn)單賦值的過(guò)程,不涉及拷貝資源的耗時(shí)操作,自然執(zhí)行效率大大提高。

移動(dòng)賦值運(yùn)算符函數(shù)

在調(diào)用賦值運(yùn)算符時(shí),如果右邊傳入的參數(shù)是右值引用對(duì)象,就會(huì)調(diào)用移動(dòng)賦值運(yùn)算符函數(shù)。同樣,如果沒(méi)有自定義移動(dòng)賦值運(yùn)算符函數(shù),那么編譯器也會(huì)自動(dòng)生成,默認(rèn)實(shí)現(xiàn)是遍歷調(diào)用成員屬性的移動(dòng)賦值運(yùn)算符函數(shù)并移動(dòng)成員屬性的數(shù)據(jù)到左邊參數(shù)對(duì)象。

一般聲明形式如下:

T& T::operator=(C&& other);

基于上面的簡(jiǎn)單例子:

class MB // MemoryBlock
{
public:
    // ...
    // 移動(dòng)賦值運(yùn)算符函數(shù)
    MB& MB::operator=(MB&& obj) {
        if (this != &obj) {
            if (buf != nullptr) {
                delete[] buf;
            }
            // 移動(dòng)源對(duì)象數(shù)據(jù)到新對(duì)象
            size = obj.size;
            buf = obj.buf;
            // 清空源對(duì)象狀態(tài)
            // 避免析構(gòu)函數(shù)多次釋放資源
            obj.size = 0;
            obj.buf = nullptr;
        }
        return *this;
    }
}

移動(dòng)賦值運(yùn)算符函數(shù)的執(zhí)行過(guò)程,同樣僅僅是簡(jiǎn)單賦值的過(guò)程,執(zhí)行效率明顯遠(yuǎn)超復(fù)制操作。

總結(jié)

回顧文首的示例代碼,由于 C++ 11 加入了返回值優(yōu)化 RVO(Return Value Optimization) 的特性,所以代碼無(wú)需變更即可獲得效率提升。對(duì)于部分編譯器而言,比如 IBM Compiler、Visual C++ 2010 等,已經(jīng)提前具備返回值優(yōu)化的支持。

到此這篇關(guān)于詳解C++中移動(dòng)語(yǔ)義的概念與使用的文章就介紹到這了,更多相關(guān)C++移動(dòng)語(yǔ)義內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vc++ 控件List Control用法總結(jié)

    Vc++ 控件List Control用法總結(jié)

    這篇文章主要介紹了Vc++ 控件List Control用法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • C語(yǔ)言代碼實(shí)現(xiàn)猜數(shù)字游戲

    C語(yǔ)言代碼實(shí)現(xiàn)猜數(shù)字游戲

    大家好,本篇文章主要講的是C語(yǔ)言代碼實(shí)現(xiàn)猜數(shù)字游戲,感興趣的同學(xué)趕快來(lái)看一看了吧,對(duì)你有幫助的話(huà)記得收藏一下
    2022-01-01
  • 深入講解Socket原理

    深入講解Socket原理

    這篇文章深入的講解Socket原理,并附帶實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-12-12
  • 淺談C語(yǔ)言共用體和與結(jié)構(gòu)體的區(qū)別

    淺談C語(yǔ)言共用體和與結(jié)構(gòu)體的區(qū)別

    下面小編就為大家?guī)?lái)一篇淺談C語(yǔ)言共用體和與結(jié)構(gòu)體的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • C語(yǔ)言關(guān)于時(shí)間復(fù)雜度詳解

    C語(yǔ)言關(guān)于時(shí)間復(fù)雜度詳解

    大家好,本篇文章主要講的是C語(yǔ)言關(guān)于時(shí)間復(fù)雜度詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下,方便下次瀏覽
    2022-01-01
  • 利用簡(jiǎn)潔的C語(yǔ)言代碼解決跳臺(tái)階問(wèn)題與約瑟夫環(huán)問(wèn)題

    利用簡(jiǎn)潔的C語(yǔ)言代碼解決跳臺(tái)階問(wèn)題與約瑟夫環(huán)問(wèn)題

    這篇文章主要介紹了利用簡(jiǎn)潔的C語(yǔ)言代碼解決跳臺(tái)階問(wèn)題與約瑟夫環(huán)問(wèn)題的方法,跳臺(tái)階問(wèn)題與約瑟夫環(huán)問(wèn)題是常見(jiàn)的基礎(chǔ)算法題目,需要的朋友可以參考下
    2016-02-02
  • C語(yǔ)言算法的定義及分析詳解

    C語(yǔ)言算法的定義及分析詳解

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言算法的定義及分析,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C語(yǔ)言中進(jìn)行函數(shù)指針回調(diào)的實(shí)現(xiàn)步驟

    C語(yǔ)言中進(jìn)行函數(shù)指針回調(diào)的實(shí)現(xiàn)步驟

    在 C 語(yǔ)言中,函數(shù)指針的回調(diào)是一種強(qiáng)大的編程技術(shù),它允許我們?cè)谔囟ǖ氖录l(fā)生或特定的條件滿(mǎn)足時(shí),調(diào)用由用戶(hù)定義的函數(shù),這種機(jī)制增加了程序的靈活性和可擴(kuò)展性,使得代碼更具通用性和可重用性,本文給大家介紹了C語(yǔ)言中進(jìn)行函數(shù)指針回調(diào)的實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2024-07-07
  • win10環(huán)境下C++ vs2015編譯opencv249的教程

    win10環(huán)境下C++ vs2015編譯opencv249的教程

    這篇文章主要介紹了win10環(huán)境下C++ vs2015編譯opencv249的教程,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • DOS簡(jiǎn)易版C語(yǔ)言貪吃蛇

    DOS簡(jiǎn)易版C語(yǔ)言貪吃蛇

    這篇文章主要為大家詳細(xì)介紹了DOS簡(jiǎn)易版C語(yǔ)言貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11

最新評(píng)論

大石桥市| 历史| 平阴县| 泽州县| 海南省| 邵武市| 青河县| 瑞安市| 新绛县| 乌拉特后旗| 永川市| 泽库县| 上饶县| 方城县| 呼伦贝尔市| 宜城市| 华安县| 南溪县| 唐河县| 当雄县| 嘉荫县| 濮阳县| 涡阳县| 康平县| 襄樊市| 广元市| 江永县| 黑水县| 昌黎县| 永寿县| 武陟县| 安吉县| 乐都县| 天津市| 内丘县| 邢台市| 宜宾县| 铜梁县| 襄垣县| 汝城县| 天等县|