簡體   English   中英

如何在深度復制中使用Constructor分配內存?

[英]How to allocate memory with Constructor in deep copy?

我正在嘗試了解Deep Copy。 但是我只是對通過調用Constructor動態分配內存感到困惑

這是我成功完成的深層復制程序:

#include<iostream>
using namespace std;
class A{
    public:
    int *p;
    A(){
        p=new int;
    }
    void set(int b){
        *p=b;
    }
    int get(){
        return *p;
    }
    void operator=(const A &k){
        p = new int;
        *p=*(k.p);
    }
    ~A(){
        delete p;
    }
};
int main()
{
    A obj;
    obj.set(3);
    A obj1;
    obj1=obj;
    obj1.set(5);
    cout << obj.get() << endl;
    cout << obj1.get() << endl;
}

現在我只想問我創建了兩個對象,構造函數將調用兩次,並且在構造函數中動態分配內存。

那么我的問題是,指針應該指向兩個不同的動態內存位置(2個對象和2個指針),或者該指針與靜態數據成員相同(那么就不需要深度復制了)? 表示所有類對象的一個​​指針。

如果創建該類的兩個實例,則它們將具有兩個不同的p成員,每個成員在內存中包含不同區域的不同地址,是的。
您可能可以判斷是否運行程序:它將顯示3和5,如果指針相同,則將顯示5兩次。

編輯:根據要求,進行一些補充說明(以及評論中所講內容的摘要)

首先,您的operator=正在泄漏內存,相反,您應記住在重新分配內存之前先釋放已在p中分配的內存:

void operator=(const A &k){
    delete p;
    // as JoshuaGreen states in the comments, you can set p to nullptr
    // here, that way, if new fails and throws, p will be set to nullptr
    // and you'll know it doesn't contain anything (you'll have to test
    // it in other methods to benefit from this modification though,
    // but it will be safer)
    p = nullptr;
    p = new int;
    *p=*(k.p);
}

盡管在這種特定情況下,您可以避免重新分配:

void operator=(const A &k){
    // p = new int; // not needed
    *p=*(k.p);
}

現在,重載賦值operator=確實很重要(而您實際上忘記了重載副本構造函數),讓我們看看如果未定義此賦值operator=會發生什么。
您的課程看起來像這樣:

#include<iostream>
using namespace std;
class A{
public:
    int *p;

    A(){
        p=new int;
    }

    void set(int b){
        *p=b;
    }

    int get(){
        return *p;
    }

    ~A(){
        delete p;
    }
};

但是實際上,編譯器會為您生成一個隱式定義的默認副本構造函數和默認賦值operator =。 當然,您看不到它們的實現,但是它們的行為與定義該類的行為完全相同:

#include<iostream>
using namespace std;
class A{
public:
    int *p;
    A(){
        p=new int;
    }

    A(const A& other) :
    p(other.p) {} // ! we're copying the pointer instead of reallocating memory

    void set(int b){
        *p=b;
    }

    int get(){
        return *p;
    }

    A& operator=(const A& other){
        p = other.p; // same here!
    }

    ~A(){
        delete p;
    }
};

當您上課時要處理動態分配的內存,那很不好。 讓我們來看看您的主系統會發生什么:

int main()
{
    // allocate a new pointer to int, let's call it p
    A obj;
    // set the content of p to 3
    obj.set(3);
    // allocate a new pointer to int, let's call it p1
    A obj1;
    // /!\
    // instead of copying the content of p to the content of p1, we're
    // actually doing p1 = p here! we're leaking memory AND the two
    // objects point on the same memory!
    obj1=obj;
    // set the content of p1 to 5, but p1 is now equal to p because of
    // the bad assignment, so we're also setting p's content to 5
    obj1.set(5);
    // print the content of p (5)
    cout << obj.get() << endl;
    // print the content of p1 (5)
    cout << obj1.get() << endl;
}
// delete the contents of p and p1 /!\ we're actually deleting the same
// allocated memory twice! that's bad

這就是為什么您必須重新定義“三者” (復制構造函數,復制分配運算符和析構函數)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM