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

C++右值引用問題解決

 更新時(shí)間:2023年06月20日 08:39:19   作者:dyyfyyds_  
本文主要介紹了C++右值引用問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、右值引用與函數(shù)重載

class Int
{
    int value;
public:
    Int(int x = 0) :value(x) { cout << "create " << this << endl; }
    ~Int() { cout << "destroy " << this << endl; }
    Int(const Int& it) :value(it.value)
    {
        cout << &it << " copy " << this << endl;
    }
    Int& operator=(const Int& it)
    {
        if (this != &it)
        {
            value = it.value;
        }
        cout << &it << " operator= " << this << endl;
        return *this;
    }
    void PrintValue()const
    {
        cout<<"value: "<<value<<endl;
    }
    Int& SetValue(int x)
    {
        value=x;
        return *this;
    }
};
//void func(Int a){}//會(huì)和void fun(Int&& c)形成二義性,原因是無名對(duì)象即可以賦值給對(duì)象也可以賦值給右值引用
void func(Int& a)
{
    cout<<"lvalue_reference"<<endl;
}
void func(const Int& b)
{
    cout<<"lvalue_const_reference"<<endl;
}
void func(Int&& c)
{
    cout<<"rvalue_reference"<<endl;
}
int main()
{
    Int x(10);
    const Int y(20);
    func(x);//優(yōu)先匹配func(Int& a),沒有就匹配func(const Int& b)
    func(y);//只能匹配func(const Int& b)
    func(Int(30));//優(yōu)先匹配func(Int&& c),沒有就匹配func(const Int& b)
    Int z(10);
    func((Int&&)z);//調(diào)用func(Int&& c)
    func((const Int&&)z);//調(diào)用func(const Int& b)
    return 0;
}

2、右值引用優(yōu)化性能,避免深拷貝

class MyString
{
private:
    char* str;
public:
    MyString(const char* p=nullptr):str(nullptr)
    {
        if(p!=nullptr)
        {
            int n=strlen(p)+1;
            str=new char[n];
            strcpy_s(str,n,p);
        }
        cout<<"Create MyString"<<this<<endl;
    }
    ~MyString()
    {
        if(str!=nullptr)
        {
            delete[] str;
            str=nullptr;
        }
        str=nullptr;
    }
    MyString(const MyString& st):str(nullptr)//深拷貝
    {
        if(st.str!=nullptr)
        {
            int n=strlen(st.str)+1;
            str=new char[n];
            strcpy_s(str,n,st.str);
        }
        cout<<"Copy Create MyString"<<this<<endl;
    }
    MyString& operator=(const MyString& st)//深賦值
    {
        if(this==&st||str==st.str)
        {
            return *this;
        }
        delete[] str;//str為空時(shí)也可以進(jìn)行delete,因?yàn)閐elete調(diào)用free,在free中會(huì)進(jìn)行判空
        int n=strlen(st.str)+1;
        str=new char[n];
        strcpy_s(str,n,st.str);
        cout<<this<<"operator= MyString"<<&st<<endl;
        return *this;
    }
    void Print()const
    {
        if(str!=nullptr)
        {
            cout<<str<<endl;
        }
    }
};

2.1使用深拷貝和深復(fù)制會(huì)對(duì)堆區(qū)空間造成巨大影響

MyString func(const char* p)
{
    MyString tmp(p);
    return tmp;
}
int main()
{
    MyString s1("hello");
    s1=func("helloworld");
    s1.Print();
    return 0;
}

在main函數(shù)中能看見的字符串"hello"和"helloworld"均存放在.data區(qū),p指針指向的也是.data區(qū)的"helloworld"。運(yùn)行時(shí)進(jìn)入主函數(shù),首先創(chuàng)建s1對(duì)象,在堆區(qū)空間申請(qǐng)空間存放字符串"hello",s1.str指向該堆區(qū)空間。

再調(diào)用func()函數(shù),進(jìn)入func()函數(shù)先創(chuàng)建tmp對(duì)象,在堆區(qū)申請(qǐng)空間存放字符串"helloworld",tmp.str指向該堆區(qū)空間。

返回時(shí),使用tmp對(duì)象構(gòu)建將亡值對(duì)象xvalue,同樣的,在堆區(qū)申請(qǐng)和tmp所申請(qǐng)大小相同的空間,將字符串"helloworld"賦值過去進(jìn)行存放,xvalue.str指向該堆區(qū)空間。需要注意的是xvalue這個(gè)將亡值對(duì)象是在main棧幀中創(chuàng)建的,而不是func()函數(shù)棧幀中。創(chuàng)建完將亡值對(duì)象后,func()函數(shù)結(jié)束銷毀tmp對(duì)象,將其所指向的堆區(qū)空間進(jìn)行釋放。

再回到主函數(shù),將該將亡值對(duì)象賦值給s1對(duì)象時(shí),調(diào)用賦值函數(shù)。首先申請(qǐng)和將亡值對(duì)象申請(qǐng)大小相同的空間,將字符串"helloworld"賦值過去進(jìn)行存放,釋放s1對(duì)象開始指向的堆區(qū)空間,之后再將s1.str重新指向新申請(qǐng)的空間。析構(gòu)所有對(duì)象這樣整個(gè)程序結(jié)束。

由此看來,深拷貝在一些情況下嚴(yán)重干擾堆空間,對(duì)其不停的申請(qǐng)和釋放。

2.2使用移動(dòng)拷貝構(gòu)造和移動(dòng)賦值提升性能(移動(dòng)資源)

//移動(dòng)拷貝構(gòu)造
MyString(MyString&& st):str(nullptr)
{
    str=st.str;
    st.str=nullptr;
    cout<<"Move Copy Create"<<endl;
}
//移動(dòng)賦值
MyString& operator=(MyString&& st)
{
    if(this==&st)return *this;
    delete[] str;
    str=st.str;
    st.str=nullptr;
    cout<<"Move Operator= "<<endl;
    return *this;
}

加入移動(dòng)拷貝構(gòu)造和移動(dòng)賦值后再執(zhí)行下面代碼:

MyString func(const char* p)
{
    MyString tmp(p);
    return tmp;
}
int main()
{
    MyString s1("hello");
    s1=func("helloworld");
    s1.Print();
    return 0;
}

同樣的,運(yùn)行時(shí)進(jìn)入主函數(shù),首先創(chuàng)建s1對(duì)象,在堆區(qū)空間申請(qǐng)空間存放字符串"hello",s1.str指向該堆區(qū)空間。

再調(diào)用func()函數(shù),進(jìn)入func()函數(shù)先創(chuàng)建tmp對(duì)象,在堆區(qū)申請(qǐng)空間存放字符串"helloworld",tmp.str指向該堆區(qū)空間。

返回時(shí)tmp為左值對(duì)象,但系統(tǒng)認(rèn)為在func函數(shù)中定義的局部對(duì)象tmp其生存期只在該函數(shù)中,使用return返回tmp對(duì)象時(shí),認(rèn)為是要將tmp的資源進(jìn)行移動(dòng),就會(huì)將其看成是將亡值。(系統(tǒng)“作弊”)

所以在func函數(shù)返回前會(huì)調(diào)用移動(dòng)拷貝構(gòu)造函數(shù)將tmp對(duì)象的資源移動(dòng)給創(chuàng)建的xvalue將亡值,func函數(shù)結(jié)束,析構(gòu)tmp對(duì)象。

回到main函數(shù)時(shí),將將亡值xvalue賦值給s1對(duì)象時(shí),調(diào)用移動(dòng)賦值函數(shù),將xvalue的資源再次移動(dòng)給s1對(duì)象,賦值結(jié)束后xvalue將亡值對(duì)象消亡,打印s1的內(nèi)容,析構(gòu)所有對(duì)象程序結(jié)束。

在這個(gè)過程中,并沒有多次反復(fù)的申請(qǐng)空間和釋放空間,而是將申請(qǐng)的空間在多個(gè)對(duì)象之間進(jìn)行移動(dòng),這樣就使得程序的性能提高。

如果將str設(shè)置為公有,即可在func和主函數(shù)中打印str的值,會(huì)發(fā)現(xiàn)tmp和func("helloworld")以及賦值完成后的s1的str值都相同,說明他們一直指向同一塊內(nèi)存空間。

到此這篇關(guān)于C++右值引用問題的文章就介紹到這了,更多相關(guān)C++右值引用問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于C語言實(shí)現(xiàn)的掃雷游戲代碼

    基于C語言實(shí)現(xiàn)的掃雷游戲代碼

    這篇文章主要介紹了基于C語言實(shí)現(xiàn)的掃雷游戲代碼,對(duì)于學(xué)習(xí)游戲開發(fā)的朋友有一定的借鑒價(jià)值,需要的朋友可以參考下
    2014-08-08
  • 基于C語言實(shí)現(xiàn)靜態(tài)通訊錄的示例代碼

    基于C語言實(shí)現(xiàn)靜態(tài)通訊錄的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用C語言實(shí)現(xiàn)一個(gè)簡單的靜態(tài)通訊錄,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2022-07-07
  • C語言錯(cuò)誤信息報(bào)告strerror函數(shù)和perror函數(shù)詳解

    C語言錯(cuò)誤信息報(bào)告strerror函數(shù)和perror函數(shù)詳解

    這篇文章主要介紹了C語言錯(cuò)誤信息報(bào)告strerror函數(shù)和perror函數(shù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • C++11新特性全解析新的類功能、lambda、包裝器詳解

    C++11新特性全解析新的類功能、lambda、包裝器詳解

    本文主要介紹了C++11中新增的移動(dòng)語義、默認(rèn)函數(shù)、刪除函數(shù)、override和final關(guān)鍵字,以及STL中的新容器和接口、lambda表達(dá)式、function和bind函數(shù)模板,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • C++中的bind實(shí)踐代碼

    C++中的bind實(shí)踐代碼

    std::bind是C++中的一個(gè)函數(shù)適配器,用于預(yù)先固定函數(shù)的某些參數(shù),生成一個(gè)新的函數(shù)對(duì)象,它通過占位符來實(shí)現(xiàn)參數(shù)的占位和重排,本文介紹C++中的bind代碼實(shí)踐,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • Windows下Qt讀取系統(tǒng)的內(nèi)存、CPU、GPU等使用信息的示例代碼

    Windows下Qt讀取系統(tǒng)的內(nèi)存、CPU、GPU等使用信息的示例代碼

    在當(dāng)今計(jì)算機(jī)應(yīng)用廣泛的領(lǐng)域中,了解系統(tǒng)的內(nèi)存、CPU和GPU使用情況是非常重要的,本文將介紹如何使用Qt和Windows API來讀取系統(tǒng)的內(nèi)存、CPU和GPU使用詳細(xì)信息,將提供一個(gè)完整的示例代碼,需要的朋友可以參考下
    2024-01-01
  • c++雙向鏈表操作示例(創(chuàng)建雙向鏈、雙向鏈表中查找數(shù)據(jù)、插入數(shù)據(jù)等)

    c++雙向鏈表操作示例(創(chuàng)建雙向鏈、雙向鏈表中查找數(shù)據(jù)、插入數(shù)據(jù)等)

    這篇文章主要介紹了c++雙向鏈表操作示例,包括創(chuàng)建雙向鏈、刪除雙向鏈表、雙向鏈表中查找數(shù)據(jù)、插入數(shù)據(jù)等,需要的朋友可以參考下
    2014-05-05
  • C++中httplib的使用小結(jié)

    C++中httplib的使用小結(jié)

    本文主要介紹了C++中httplib的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-05-05
  • 在Qt中遍歷QStringList子集并存儲(chǔ)的三種方法

    在Qt中遍歷QStringList子集并存儲(chǔ)的三種方法

    本文介紹了在Qt中遍歷QStringList子集并存儲(chǔ)的三種方法:1)使用mid()函數(shù)提取連續(xù)范圍的元素;2)通過循環(huán)遍歷指定索引范圍;3)利用filter()函數(shù)按內(nèi)容篩選,每種方法適用于不同場景,需要的朋友可以參考下
    2026-01-01
  • C++?OpenCV實(shí)戰(zhàn)之零部件的自動(dòng)光學(xué)檢測

    C++?OpenCV實(shí)戰(zhàn)之零部件的自動(dòng)光學(xué)檢測

    這篇文章主要為大家介紹一個(gè)C++?OpenCV的實(shí)戰(zhàn)——零部件的自動(dòng)光學(xué)檢測,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-09-09

最新評(píng)論

兴隆县| 镇安县| 枣强县| 大余县| 望城县| 青冈县| 怀来县| 云龙县| 桐城市| 益阳市| 博湖县| 武义县| 沙雅县| 万宁市| 喀什市| 平顺县| 黎川县| 彭山县| 理塘县| 额敏县| 邯郸县| 通道| 白水县| 漾濞| 仁怀市| 湘潭县| 莱芜市| 新郑市| 鄂温| 独山县| 扶绥县| 曲沃县| 武山县| 汶川县| 新泰市| 应用必备| 宁河县| 大关县| 辉南县| 扶绥县| 大名县|