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

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

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

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

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

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

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

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

如上圖,我們給類(lèi)A提供了一個(gè)有參的構(gòu)造函數(shù),所以此時(shí),如果再去主函數(shù)定義一個(gè)無(wú)參的對(duì)象時(shí),編譯器就會(huì)提示“類(lèi)A不存在默認(rèn)構(gòu)造函數(shù)”,這就說(shuō)明如果自己定義了有參構(gòu)造函數(shù),那么就不會(huì)提供默認(rèn)的無(wú)參構(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;
}

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

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

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

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

2.深拷貝和淺拷貝問(wèn)題

淺拷貝:就是簡(jiǎn)單的賦值操作

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

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

#include<iostream>
using namespace std;
class A {
    int num;
    int* p;
public:
    A() {
        num = 0;
        p = nullptr;
        cout << "調(diào)用無(wú)參構(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;
}

在類(lèi)A中我們定義了一個(gè)指針變量,在有參構(gòu)造函數(shù)中,我們?cè)诙褏^(qū)開(kāi)辟了一塊空間。在主函數(shù)數(shù)中,定義對(duì)象b要走拷貝構(gòu)造函數(shù)。下面我們來(lái)運(yùn)行這段代碼:

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

那么解決的辦法就是重寫(xiě)拷貝構(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)用無(wú)參構(gòu)造" << endl;
    }
    A(int a) {
        num = a;
        p = new int[num];
        cout << "調(diào)用有參構(gòu)造" << endl;
    }
    A(const A& other) {//萬(wàn)能引用,避免實(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;
}

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

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

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

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

#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é)

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

相關(guān)文章

  • C語(yǔ)言指針入門(mén)的簡(jiǎn)單實(shí)例教程

    C語(yǔ)言指針入門(mén)的簡(jiǎn)單實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言指針入門(mén)的簡(jiǎn)單實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • vscode終端中打不開(kāi)conda虛擬包管理的解決

    vscode終端中打不開(kāi)conda虛擬包管理的解決

    本文主要介紹了vscode終端中打不開(kāi)conda虛擬包管理的解決,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • C語(yǔ)言 選擇排序算法詳解及實(shí)現(xiàn)代碼

    C語(yǔ)言 選擇排序算法詳解及實(shí)現(xiàn)代碼

    本文主要介紹C語(yǔ)言 選擇排序算法,這里對(duì)排序算法做了詳細(xì)說(shuō)明,并附代碼示例,有需要的小伙伴可以參考下
    2016-08-08
  • C++ Vector迭代器失效問(wèn)題的解決方法

    C++ Vector迭代器失效問(wèn)題的解決方法

    最近我學(xué)習(xí)了C++中的迭代器失效問(wèn)題,迭代器失效問(wèn)題是非常非常重要的,所以特意整理出來(lái)一篇文章供我們一起復(fù)習(xí)和學(xué)習(xí)
    2022-08-08
  • C語(yǔ)言動(dòng)態(tài)內(nèi)存規(guī)劃詳解

    C語(yǔ)言動(dòng)態(tài)內(nèi)存規(guī)劃詳解

    這篇文章主要介紹了C語(yǔ)言動(dòng)態(tài)內(nèi)存的規(guī)劃,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • C語(yǔ)言關(guān)鍵字總結(jié)解析

    C語(yǔ)言關(guān)鍵字總結(jié)解析

    這篇文章主要介紹了C語(yǔ)言關(guān)鍵字總結(jié)解析,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是本文的詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語(yǔ)言封裝函數(shù)字符串練習(xí)匯總分享

    C語(yǔ)言封裝函數(shù)字符串練習(xí)匯總分享

    這篇文章主要介紹了C語(yǔ)言封裝函數(shù)字符串練習(xí)匯總分享,分享內(nèi)容有字符串查找、字符串拼接、字符串轉(zhuǎn)整數(shù)等內(nèi)容,需要而小伙伴可以參考一下
    2022-03-03
  • c++實(shí)現(xiàn)對(duì)輸入數(shù)組進(jìn)行快速排序的示例(推薦)

    c++實(shí)現(xiàn)對(duì)輸入數(shù)組進(jìn)行快速排序的示例(推薦)

    下面小編就為大家?guī)?lái)一篇c++實(shí)現(xiàn)對(duì)輸入數(shù)組進(jìn)行快速排序的示例(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • 使用?Visual?Studio?2022?開(kāi)發(fā)?Linux?C++?應(yīng)用程序的過(guò)程詳解

    使用?Visual?Studio?2022?開(kāi)發(fā)?Linux?C++?應(yīng)用程序的過(guò)程詳解

    Visual?Studio?2022?引入了用于?Linux?C++?開(kāi)發(fā)的本機(jī)?WSL2?工具集,可以構(gòu)建和調(diào)試?Linux?C++?代碼,并提供了非常好的?Linux?文件系統(tǒng)性能、GUI?支持和完整的系統(tǒng)調(diào)用兼容性,這篇文章主要介紹了使用Visual?Studio?2022?開(kāi)發(fā)?Linux?C++?應(yīng)用程序,需要的朋友可以參考下
    2021-11-11
  • C/C++?Qt?TabWidget?實(shí)現(xiàn)多窗體創(chuàng)建詳解

    C/C++?Qt?TabWidget?實(shí)現(xiàn)多窗體創(chuàng)建詳解

    TabWidget組件配合自定義Dialog組件,可實(shí)現(xiàn)一個(gè)復(fù)雜的多窗體分頁(yè)結(jié)構(gòu)。這篇文章就主要介紹了如何通過(guò)TabWidget實(shí)現(xiàn)多窗體的創(chuàng)建,感興趣的小伙伴可以了解一下
    2021-12-12

最新評(píng)論