C++ 類的深拷貝和淺拷貝完美解決


//類的深拷貝和淺拷貝
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Point{
public:
    Point(int _a,int _b,const char *pin/*in*/){
        x = _a;
        y = _b;
        remark = (char *)malloc(sizeof(char)*(strlen(pin) + 1));
        strcpy(remark, pin);
        cout << "我是自定義的有參構造函數4" << endl;
    }
    Point(Point &pm){
        cout << "我是自定義的拷貝構造函數3" << endl;
        //修改拷貝構造函數
        x = pm.x;
        y = pm.y;
        //remark = pm.remark; 這句話錯誤
        //修改后的方案
        remark = (char *)malloc(sizeof(char)*(strlen(pm.remark) + 1));
        strcpy(remark, pm.remark);
    }
    ~Point(){
        if (remark!=NULL)
        {
            free(remark);
        }
        cout << "我是自定義的析構函數2" << endl;
    }
    void GetPremark(){
        printf("指針變量remark的地址是%x\n", remark);
    }
    //BBB---運算符重載
    void operator=(Point &pm){
        //CCC  解決方案第三步
        if (remark!=NULL)
        {
            free(remark);
            remark = NULL;
        }
        //解決方案改良第二步(以下)
        x = pm.x;
        y = pm.y;
        remark = (char *)malloc(sizeof(char)*(strlen(pm.remark) + 1));
        strcpy(remark, pm.remark);
    }
private:
    int x;
    int y;
    char *remark;
};

void ProtectA(){
    Point p1(1, 1, "123");
    Point p2 = p1;
    printf("這是p1中字符指針的地址\n");
    p1.GetPremark();//打印  ad95e8
    printf("這是p2中字符指針的地址\n");
    p2.GetPremark();//打印  ad95e8
    //這說明類對象之間拷貝指針拷貝了指針變量的值(兩個指針指向同一片內存),並沒有新分配內存 //出現問題:當先調用p2(函數的壓棧,先定義后釋放)的析構函數的時候,會釋放指針變量remark指向的內存,
    //當調用p1的析構函數的時候就會報錯

    //解決方案第一步--修改類的拷貝構造函數
    //BUG事例
    //Point p3;//報錯  error C2512: “Point”: 沒有合適的默認構造函數可用
    //這說明只要定義了有參構造函數,那么c++編譯器就不會自動創建無參構造函數
    Point p4(2,3,"456");
    //賦值操作
    //p4 = p2;
    //分析:賦值操作會將p2的所有值(包括指針變量的值)拷貝到p4對象中
    //此時又會出現兩個指針變量指向同一片內存的情況,當析構對象p4的時候,會釋放指針變量指向的內存
    //那么析構p2的時候又會報錯(那塊內存已經被釋放了,被釋放了2次)

    //解決方案第二步--"="運算符重載 //詳情見 BBB  運算符重載的使用場景
    p4 = p2;

    //BUG事例
    p4 = p1;

    //分析:當執行p4 = p2; p4 = p1;仔細分析"="重載函數發現,p4 = p2;p4會開辟一塊內存N1,
    //p4 = p1;p4會再開辟一塊內存N2,此時N1這塊內存永遠不會被釋放,這就造成了內存泄漏 //為了解決這個問題  

    //解決方案第三步
    //我們可以在執行"="重載函數之前判斷一下指針變量指向的內存又沒有釋放, //(所以要確定--定義對象的時候必須要分配指針變量的內存或者將指針變量置空)
    ///詳情見 CCC
}


void main(){
    
    ProtectA();


    system("pause");
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM