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

C++實現(xiàn)拷貝構造函數(shù)的方法詳解

 更新時間:2022年09月20日 08:20:23   作者:Mi?ronin  
拷貝構造函數(shù)是構造函數(shù)的一個重載,因此顯式的定義了拷貝構造,那么編譯器也不再默認生成構造函數(shù)。本文主要介紹了C++實現(xiàn)拷貝構造函數(shù)的方法,需要的可以參考一下

引入

對于普通類型的對象來說,他們之間的復制很簡單:

int a = 10;
int b = a;

但是對于類對象來說,其中會存在許多的成員變量。

#include <iostream>
using namespace std;

class CExample {
private:
     int a;
public:
      //構造函數(shù)
     CExample(int b)
     { a = b;}

      //一般函數(shù)
     void Show ()
     {
        cout<<a<<endl;
      }
};

int main()
{
     CExample A(100);
     CExample B = A; //注意這里的對象初始化要調(diào)用拷貝構造函數(shù),而非賦值
      B.Show ();
     return 0;
}

從以上代碼可以看出系統(tǒng)為對象 B 分配了內(nèi)存并完成了與對象 A 的復制過程。就類對象而言,相同類型的類對象是通過拷貝構造函數(shù)來完成整個復制過程的。

下面這個則是拷貝構造函數(shù)的工作過程

#include <iostream>
using namespace std;

class CExample {
private:
    int a;
public:
    //構造函數(shù)
    CExample(int b)
    { a = b;}
    
    //拷貝構造函數(shù)
    CExample(const CExample& C)
    {
        a = C.a;
    }

    //一般函數(shù)
    void Show ()
    {
        cout<<a<<endl;
    }
};

int main()
{
    CExample A(100);
    CExample B = A; // CExample B(A); 也是一樣的
     B.Show ();
    return 0;
} 

在這里CExample(const CExample& C) 就是我們自定義的拷貝構造函數(shù)。

一.什么是拷貝構造函數(shù)

同一個類的對象在內(nèi)存中有完全相同的結構,如果作為一個整體進行復制或稱拷貝是完全可行的。這個拷貝過程只需要拷貝數(shù)據(jù)成員,而函數(shù)成員是共用的(只有一份拷貝)。在建立對象時可用同一類的另一個對象來初始化該對象的存儲空間,這時所用的構造函數(shù)稱為拷貝構造函數(shù)。

拷貝構造函數(shù)本質(zhì)上來說也是構造函數(shù)。

二.什么情況下使用拷貝構造函數(shù)

一般來說有以下三種情況:

  • 用舊對象去初始化新對象
  • 值傳遞—參數(shù)是類類型的值類型,從實參傳遞給形參的過程,是用實參去構造形參
  • 函數(shù)返回值是值類型–用局部對象去構造臨時對象調(diào)用拷貝構造
class A
{
public:
    A(int i = 0):m_i(i)
    {
        cout<<"A(int) "<<m_i<<endl;
    }
    A(const A &a):m_i(a.m_i)
    {
        cout<<"A(A) "<<m_i<<endl;
    }
    ~A()
    {
        cout<<"~A "<<m_i<<endl;
    }
private:
    int m_i;
};
void fn(A t) //2.將c傳遞給t的過程,是值傳遞,此時臨時對象形參t是新對象,用c去構造t,調(diào)用拷貝構造
{
    cout<<"fn end"<<endl;
    //在退出fn函數(shù)時,將臨時對象t釋放,調(diào)用析構函數(shù)
}
A test()
{
    A d(40); //調(diào)用普通構造A(int)構造對象d
    return d;
    /*
     3.在返回的時候,將局部對象的值給了臨時對象(值傳遞,調(diào)用拷貝構造,用舊局部對象去構造新的臨時對象)
     然后局部對象d就釋放了,臨時對象將值帶回到主調(diào)函數(shù)中后,臨時對象的值才釋放
    */
}
A fnn()
{
    A s(50); //A(int) 50
    return s; //
    /*1.s->臨時對象  拷貝構造
    2.析構函數(shù)局部對象s
    */
}
void main()
{
    A a(20);  //A(int) 20
    A b = a;  //1.用a初始化b A(A)
    cout<<"fn"<<endl;
    A c(30); //A(int) 30
    fn(c);
    cout<<"test"<<endl;
    c = test(); //臨時對象將值賦給c(調(diào)用賦值函數(shù))之后,調(diào)用析構,析構臨時對象
    cout<<"fnn"<<endl;
    A t = fnn(); //臨時對象初始化新對象t,是否會調(diào)用拷貝構造?--調(diào)用了,不過編譯器做過優(yōu)化
    cout<<"main end"<<endl;
}

三.使用拷貝構造函數(shù)需要注意什么

拷貝構造函數(shù)是構造函數(shù)的一個重載形式。

拷貝構造函數(shù)的參數(shù)只有一個且必須使用引用傳參,使用傳值方式會引發(fā)無窮遞歸調(diào)用。

若未顯示定義,系統(tǒng)生成默認的拷貝構造函數(shù)。默認的拷貝構造函數(shù)對象按內(nèi)存存儲按字節(jié)序完成拷貝,稱為:位拷貝。

四.深拷貝淺拷貝

4.1 淺拷貝

所謂淺拷貝,指的是在對象復制時,只對對象中的數(shù)據(jù)成員進行簡單的賦值,默認拷貝構造函數(shù)執(zhí)行的也是淺拷貝。大多情況下“淺拷貝”已經(jīng)能很好地工作了,但是一旦對象存在了動態(tài)成員,指針,那么淺拷貝就會出現(xiàn)一些問題。

對于下面函數(shù)來說有指針作為數(shù)據(jù)成員,則用s1對象去構造s2對象的時候,調(diào)用默認拷貝構造,用s1中的數(shù)據(jù)成員指針m_str去初始化s2對象中的數(shù)據(jù)成員m_str,即是s2.m_str = s1.m_str,那么導致兩個對象中的指針指向同一塊內(nèi)存單元,指向的都是構造s1對象時開辟的內(nèi)存單元,所以在主函數(shù)退出時候要析構s2和s1時,將同一段空間釋放兩次出現(xiàn)內(nèi)存錯誤。

class Str
{
public:
    Str(const char *str = "")
    {
        m_str = new char[strlen(str)+1];
        strcpy(m_str,str);
    }
    ~Str()
    {
        delete[]m_str;
    }
    void Print()
    {
        cout<<m_str<<endl;
    }
private:
    char *m_str;
};
void main()
{
    Str s1("pangpang");
    Str s2(s1);
    cout<<sizeof(Str)<<endl;
    s1.Print();
    s2.Print();
}

上述程序的內(nèi)存布局:

對于指針作為數(shù)據(jù)成員的類,用s1對象去構造s2對象的時候,調(diào)用默認拷貝構造函數(shù)時,二者指向同一內(nèi)存單元,即二者的初始地址相同這里均為0X0002000,當我們構造完以后將要進行析構時,這里將會出現(xiàn)錯誤:因為析構函數(shù)要釋放空間,而這里我們的空間對應的是一塊空間,當我們析構完s2后:這一塊空間的內(nèi)容已經(jīng)被delete,而我們還需要析構s1,即:一個內(nèi)存空間析構了兩次,出現(xiàn)內(nèi)存錯誤。

為了解決上述問題 我們就需要給s2中的m_str也開辟和s1中的m_str一樣大小的空間,所以我們就需要 深拷貝 。

4.2 深拷貝

在“深拷貝”的情況下,對于對象中動態(tài)成員,就不能僅僅簡單地賦值了,而應該重新動態(tài)分配空間,如上面的例子就應該按照如下的方式進行處理:

class Str
{
public:
    Str(const char *str = "")
    {
        m_str = new char[strlen(str)+1];
        strcpy(m_str,str);
    }
    ~Str()
    {
        cout<<"~Str"<<endl;
        delete[]m_str;
    }
    Str(const Str& s)
    {
        cout<<"Str(Str)"<<endl;
        m_str = new char[strlen(s.m_str)+1]; //開辟同樣大小的空間
        strcpy(m_str,s.m_str); //將內(nèi)容拷貝成一樣的
    }
    void Print()
    {
        cout<<m_str<<endl;
    }
private:
    char *m_str;
};
void main()
{
    Str s1("pangpang");
    Str s2(s1); //拷貝構造
    s1.Print();
    s2.Print();
}

現(xiàn)在的程序內(nèi)存布局為:

各自指向一段內(nèi)存空間,但它們指向的空間具有相同的內(nèi)容,這就是所謂的“深拷貝”。

到此這篇關于C++實現(xiàn)拷貝構造函數(shù)的方法詳解的文章就介紹到這了,更多相關C++拷貝構造函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 如何通過UltraEdit解析BMP文件內(nèi)部結構(BMP位圖基礎)

    如何通過UltraEdit解析BMP文件內(nèi)部結構(BMP位圖基礎)

    我們先打開畫圖隨便畫一幅圖并采用24位bmp圖像格式保存,就得到了一張24位真彩色的位圖,下面我們來詳細分析bmp位圖的各個組成部分,感興趣的朋友跟隨小編一起看看吧
    2021-08-08
  • C語言實現(xiàn)xml構造解析器

    C語言實現(xiàn)xml構造解析器

    本文給大家分享的是使用C語言來實現(xiàn)xml構造解析器的方法和代碼,簡單易用,推薦給大家
    2016-07-07
  • Qt常用容器類的使用

    Qt常用容器類的使用

    本文主要介紹了Qt常用容器類的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • C++高級數(shù)據(jù)結構之線段樹

    C++高級數(shù)據(jù)結構之線段樹

    這篇文章主要介紹了C++高級數(shù)據(jù)結構之線段樹,文章圍繞主題的相關資料展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-05-05
  • C++?Cartographer源碼中關于傳感器的數(shù)據(jù)傳遞實現(xiàn)

    C++?Cartographer源碼中關于傳感器的數(shù)據(jù)傳遞實現(xiàn)

    這篇文章主要介紹了C++?Cartographer源碼中關于傳感器的數(shù)據(jù)傳遞實現(xiàn),前面已經(jīng)談到了Cartographer中添加軌跡的方法和傳感器的數(shù)據(jù)流動走向。發(fā)現(xiàn)在此調(diào)用了LaunchSubscribers這個函數(shù)來訂閱相關傳感器數(shù)據(jù)
    2023-03-03
  • C++中cin的返回值問題

    C++中cin的返回值問題

    這篇文章主要介紹了C++中cin的返回值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • VS報錯C6011的問題:取消對NULL指針的引用(解決方法)

    VS報錯C6011的問題:取消對NULL指針的引用(解決方法)

    這篇文章主要介紹了VS報錯C6011的問題:取消對NULL指針的引用(解決方法),C6011:取消對NULL指針的引用,發(fā)現(xiàn)是沒有進行空指針的判斷,解決方案跟隨小編一起看看吧
    2024-01-01
  • C/C++多參數(shù)函數(shù)參數(shù)的計算順序與壓棧順序的示例代碼

    C/C++多參數(shù)函數(shù)參數(shù)的計算順序與壓棧順序的示例代碼

    這篇文章主要介紹了C/C++多參數(shù)函數(shù)參數(shù)的計算順序與壓棧順序,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 詳解C語言處理算經(jīng)中著名問題百錢百雞

    詳解C語言處理算經(jīng)中著名問題百錢百雞

    古代的很多數(shù)學問題都可以用現(xiàn)代的編程語言去嘗試解決,就如本篇,將會帶你通過C語言來解決算經(jīng)中百錢百雞問題,感興趣的朋友來看看吧
    2022-02-02
  • 深入探索C++中stack和queue的底層實現(xiàn)

    深入探索C++中stack和queue的底層實現(xiàn)

    這篇文章主要介紹了C++中的stack和dequeue的底層實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09

最新評論

广汉市| 句容市| 新建县| 华容县| 庆城县| 三门县| 新安县| 江油市| 当阳市| 明溪县| 阜阳市| 嫩江县| 廉江市| 防城港市| 麟游县| 杭锦后旗| 乳山市| 通辽市| 侯马市| 比如县| 沈丘县| 霍山县| 遵义市| 星子县| 大姚县| 汉川市| 高碑店市| 墨玉县| 林西县| 揭阳市| 大同市| 临沂市| 皋兰县| 东山县| 深水埗区| 巴中市| 盘锦市| 汝南县| 廉江市| 江北区| 洞口县|