欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++右值引用問題解決

 更新時間:2023年06月20日 08:39:19   作者:dyyfyyds_  
本文主要介紹了C++右值引用問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(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){}//會和void fun(Int&& c)形成二義性,原因是無名對象即可以賦值給對象也可以賦值給右值引用
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為空時也可以進(jìn)行delete,因為delete調(diào)用free,在free中會進(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ù)制會對堆區(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"。運行時進(jìn)入主函數(shù),首先創(chuàng)建s1對象,在堆區(qū)空間申請空間存放字符串"hello",s1.str指向該堆區(qū)空間。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

相關(guān)文章

  • C++使用初始化列表的方式來初始化字段的方法

    C++使用初始化列表的方式來初始化字段的方法

    今天小編就為大家分享一篇關(guān)于C++使用初始化列表的方式來初始化字段的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 清除3389遠(yuǎn)程登錄日志

    清除3389遠(yuǎn)程登錄日志

    這篇文章主要介紹了清除3389遠(yuǎn)程登錄日志示例,需要的朋友可以參考下
    2014-01-01
  • linux根據(jù)pid獲取進(jìn)程名和獲取進(jìn)程pid(c語言獲取pid)

    linux根據(jù)pid獲取進(jìn)程名和獲取進(jìn)程pid(c語言獲取pid)

    status文件,第一行的Name即為進(jìn)程名,C程序?qū)崿F(xiàn)根據(jù)PID獲取進(jìn)程名和根據(jù)進(jìn)程名獲取PID,大家參考使用吧
    2013-12-12
  • C++實現(xiàn)圖書管理系統(tǒng)(文件操作與類)

    C++實現(xiàn)圖書管理系統(tǒng)(文件操作與類)

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++?Boost?weak_ptr智能指針超詳細(xì)講解

    C++?Boost?weak_ptr智能指針超詳細(xì)講解

    智能指針是一種像指針的C++對象,但它能夠在對象不使用的時候自己銷毀掉。雖然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷貝和賦值操作),因此很少有人使用。它是Boost各組件中,應(yīng)用最為廣泛的一個
    2022-11-11
  • C++指向類成員的指針詳解

    C++指向類成員的指針詳解

    指向類成員的指針總的來講可以分為兩大類四小類(指向數(shù)據(jù)成員還是成員函數(shù),指向普通成員還是靜態(tài)成員),希望本片文章能給你帶來幫助
    2021-09-09
  • Qt編寫地圖之實現(xiàn)跨平臺功能

    Qt編寫地圖之實現(xiàn)跨平臺功能

    這篇文章主要介紹了如何利用Qt編寫地圖應(yīng)用時實現(xiàn)跨平臺功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-02-02
  • C++下如何將TensorFlow模型封裝成DLL供C#調(diào)用

    C++下如何將TensorFlow模型封裝成DLL供C#調(diào)用

    這篇文章主要介紹了C++下如何將TensorFlow模型封裝成DLL供C#調(diào)用問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++制作DLL文件的方法詳解

    C++制作DLL文件的方法詳解

    本文主要介紹如何制作DLL,將代碼類中的方法以接口的形式暴露出來給exe程序使用。會涉及類廠創(chuàng)建方法實例、聲明DLL接口、.def文件的使用等,感興趣的可以了解一下
    2023-04-04
  • C語言簡單實現(xiàn)門禁系統(tǒng)

    C語言簡單實現(xiàn)門禁系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言簡單實現(xiàn)門禁系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評論