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

解讀構(gòu)造函數(shù)的調(diào)用規(guī)則、深拷貝與淺拷貝

 更新時間:2024年11月13日 14:08:58   作者:gemluoye  
本文主要介紹了C++中的默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)以及深拷貝和淺拷貝的概念,并通過實(shí)際代碼示例進(jìn)行了詳細(xì)講解

1.調(diào)用規(guī)則

默認(rèn)情況下,C++至少會給一個類添加三個函數(shù):

  • 默認(rèn)構(gòu)造函數(shù)(無參,函數(shù)體為空)
  • 默認(rèn)析構(gòu)函數(shù)(無參,函數(shù)體為空)
  • 默認(rèn)拷貝構(gòu)造函數(shù),對屬性進(jìn)行值拷貝

調(diào)用規(guī)則:

1.如果用戶定義了有參構(gòu)造函數(shù),C++將不在提供默認(rèn)無參構(gòu)造函數(shù),但是會提供默認(rèn)拷貝構(gòu)造函數(shù)。

如上圖,我們給類A提供了一個有參的構(gòu)造函數(shù),所以此時,如果再去主函數(shù)定義一個無參的對象時,編譯器就會提示“類A不存在默認(rèn)構(gòu)造函數(shù)”,這就說明如果自己定義了有參構(gòu)造函數(shù),那么就不會提供默認(rèn)的無參構(gòu)造函數(shù)。

#include<iostream>
using namespace std;
class A {
public:
	int num;
	A(int num) {
		this->num = num;
	}
};
int main()
{
	A a(5);
	A b(a);
	cout << b.num;
	return 0;
}

在類中我們只提供了一個有參的構(gòu)造函數(shù),我們在主函數(shù)中定義一個b對象,傳的是對象a,那么它便會走拷貝構(gòu)造的函數(shù),如果能夠輸出b.num的值為5的話,則說明提供了默認(rèn)的拷貝構(gòu)造函數(shù)。

通過打印b的num,發(fā)現(xiàn)確實(shí)是5.那么就會提供默認(rèn)的構(gòu)造函數(shù)。

2.如果用戶定義拷貝構(gòu)造函數(shù),c++不會提供其他構(gòu)造函數(shù)

可以看到當(dāng)我們僅在類A中寫了一個拷貝構(gòu)造函數(shù)時,再去主函數(shù)中定義一個無參的對象a時,就會報錯,提示“類A不存在默認(rèn)構(gòu)造函數(shù)”。

2.深拷貝和淺拷貝問題

淺拷貝:就是簡單的賦值操作

存在的問題:如果有指針指向堆區(qū)內(nèi)存時,不同對象的指針成員指向的是同一塊堆區(qū)內(nèi)存。在對象進(jìn)行釋放時,該堆區(qū)會被釋放兩次。當(dāng)一個對象修改堆區(qū)的內(nèi)容時,另一個對象的內(nèi)容也會隨著改變。

深拷貝:申請同樣大小的堆區(qū)內(nèi)存,保證兩個堆區(qū)的內(nèi)容一樣。

#include<iostream>
using namespace std;
class A {
    int num;
    int* p;
public:
    A() {
        num = 0;
        p = nullptr;
        cout << "調(diào)用無參構(gòu)造" << endl;
    }
    A(int a) {
        num = a;
        p = new int[num];
        cout << "調(diào)用有參構(gòu)造" << endl;
    }
    ~A() {
        if (p)delete[]p;
    }
};

int main() {
    A a(3);
    A b = a;
    return 0;
}

在類A中我們定義了一個指針變量,在有參構(gòu)造函數(shù)中,我們在堆區(qū)開辟了一塊空間。在主函數(shù)數(shù)中,定義對象b要走拷貝構(gòu)造函數(shù)。下面我們來運(yùn)行這段代碼:

發(fā)現(xiàn)報錯了,原因就是對象a和對象b的成員變量*p指向的是同一塊堆區(qū)內(nèi)存,再調(diào)用析構(gòu)函數(shù)時,對象b先把這塊堆區(qū)內(nèi)存釋放了,當(dāng)對象a調(diào)用析構(gòu)函數(shù)時,此時那塊堆區(qū)內(nèi)存已經(jīng)不存在了,所以會出現(xiàn)訪問內(nèi)存失敗,導(dǎo)致程序崩潰。

那么解決的辦法就是重寫拷貝構(gòu)造函數(shù),讓他們指向不同的堆區(qū)區(qū)域。代碼如下:

#include<iostream>
using namespace std;
class A {
    int num;
    int* p;
public:
    A() {
        num = 0;
        p = nullptr;
        cout << "調(diào)用無參構(gòu)造" << endl;
    }
    A(int a) {
        num = a;
        p = new int[num];
        cout << "調(diào)用有參構(gòu)造" << endl;
    }
    A(const A& other) {//萬能引用,避免實(shí)參修改形參
        num = other.num;
        p = new int[num];//保證內(nèi)存大小相同
        for (int i = 0; i < num; i++) {
            p[i] = other.p[i];//保證數(shù)據(jù)相同
        }
        cout << "調(diào)用拷貝構(gòu)造" << endl;
    }
    ~A() {
        if (p)delete[]p;
        cout << "調(diào)用析構(gòu)函數(shù)" << endl;
    }
};

int main() {
    A a(3);
    A b = a;
    return 0;
}

通過再在堆區(qū)上開辟一塊內(nèi)存,讓這塊堆區(qū)內(nèi)存上的內(nèi)容和對象a的堆區(qū)內(nèi)容一樣就行,這就是深拷貝。

程序能正常運(yùn)行。

3.string類的拷貝構(gòu)造練習(xí)

可以通過下面這個自定義string類進(jìn)一步加深對深拷貝的理解。

#include<iostream>
using namespace std;
class String {
    int size;
    char* p;
public:
    String() {
        p = nullptr;
        size = 0;
    }
    String(const char* p) {
        size = strlen(p);
        this->p = new char[size + 1];//\0,所以加一
        strcpy_s(this->p, size + 1, p);
    }
    ~String() {
        if (p)  delete[]p;
    }
    String(const String& other) {
        this->size = other.size;
        this->p = new char[size + 1];
        strcpy_s(this->p, size + 1,other.p);
    }
    void print() {
        cout << p<<endl;
    }
};
int main() {
    String str = "abcde";
    String str2(str);
    str2.print();
    return 0;
}

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解用C語言實(shí)現(xiàn)三子棋游戲流程

    詳解用C語言實(shí)現(xiàn)三子棋游戲流程

    三子棋是一種民間傳統(tǒng)游戲,又叫九宮棋、圈圈叉叉、一條龍、井字棋等。將正方形對角線連起來,相對兩邊依次擺上三個雙方棋子,只要將自己的三個棋子走成一條線,對方就算輸了
    2021-11-11
  • C++實(shí)現(xiàn)四則混合運(yùn)算計算器

    C++實(shí)現(xiàn)四則混合運(yùn)算計算器

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則混合運(yùn)算計算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • C++可變參數(shù)的實(shí)現(xiàn)方法

    C++可變參數(shù)的實(shí)現(xiàn)方法

    可變參數(shù)給編程帶來了很大的方便,在享受它帶來的方便的同時,很有必要了解一下其實(shí)現(xiàn)方式,在了解編程語言的同時,也可以擴(kuò)展編程的思路。
    2013-03-03
  • 淺談C++模板元編程

    淺談C++模板元編程

    本篇文章主要介紹了淺談C++模板元編程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • C語言實(shí)現(xiàn)彈跳小球

    C語言實(shí)現(xiàn)彈跳小球

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)彈跳小球,設(shè)置了小球分?jǐn)?shù)及過關(guān)難度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • win10環(huán)境下C++ vs2015編譯opencv249的教程

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

    這篇文章主要介紹了win10環(huán)境下C++ vs2015編譯opencv249的教程,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • linux下基于C語言的信號編程實(shí)例

    linux下基于C語言的信號編程實(shí)例

    這篇文章主要介紹了linux下基于C語言的信號編程,實(shí)例分析了信號量的基本使用技巧與相關(guān)概念,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • C++ 類的靜態(tài)成員深入解析

    C++ 類的靜態(tài)成員深入解析

    在C++中類的靜態(tài)成員變量和靜態(tài)成員函數(shù)是個容易出錯的地方,本文先通過幾個例子來總結(jié)靜態(tài)成員變量和成員函數(shù)使用規(guī)則,再給出一個實(shí)例來加深印象
    2013-09-09
  • C++?setw()函數(shù)的具體使用

    C++?setw()函數(shù)的具體使用

    本文主要介紹了C++?setw()函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 詳解C++編程中向函數(shù)傳遞引用參數(shù)的用法

    詳解C++編程中向函數(shù)傳遞引用參數(shù)的用法

    這篇文章主要介紹了詳解C++編程中向函數(shù)傳遞引用參數(shù)的用法,包括使函數(shù)返回引用類型以及對指針的引用,需要的朋友可以參考下
    2016-01-01

最新評論

西丰县| 晴隆县| 合作市| 赤水市| 宁津县| 南木林县| 江陵县| 西宁市| 山丹县| 武功县| 英吉沙县| 姜堰市| 静安区| 翼城县| 巨鹿县| 房山区| 拉萨市| 马龙县| 大冶市| 绍兴市| 贡山| 姚安县| 麦盖提县| 平安县| 舞阳县| 黑龙江省| 焉耆| 临泉县| 玛曲县| 普陀区| 景谷| 合山市| 孟村| 叶城县| 哈尔滨市| 运城市| 邵阳县| 措勤县| 灯塔市| 汤阴县| 罗江县|