使用 C++ 中的复制构造函数创建深拷贝。

huangapple go评论62阅读模式
英文:

create a deep copy by using copy constructor in c++

问题

我是初学者,正在学习C++,但我遇到了关于拷贝构造函数的问题:我需要进行深拷贝,因为我的类包含指针。我已经定义了拷贝构造函数,并创建了一个来自我的类"Number"的对象N1(2,3)。第二个对象N2通过使用拷贝构造函数进行初始化。

但是拷贝构造函数没有执行深拷贝,因为当我更改对象N1的值时,对象N2的值也会发生变化。我希望通过使用拷贝构造函数来得到两个独立的对象。

我的"Number"类:

class Number
{
private:
    int* a;
    int* b;

public:
    //默认构造函数:
    Number() {
        a = new int;
        b = new int;
        *a = 0;
        *b = 0;
    }

    //带参数的构造函数:
    Number(int val1, int val2) {
        a = new int;
        b = new int;
        *a = val1;
        *b = val2;
    }
    //拷贝构造函数:
    Number(const Number& other) {
        a = new int;
        b = new int;
        *a = *(other.a);
        *b = *(other.b);
    }

    //获取和设置方法:
    int getA() {
        return *a;
    }
    int getB() {
        return *b;
    }
    void setA(int val) {
        *a = val;
    }
    void setB(int val) {
        *b = val;
    }

    //打印方法:
    void print() {
        cout << "a的值:" << *a << " b的值:" << *b << endl;
    }
};

我的主函数:

int main()
{
    Number N1(2, 3), N2;

    N1.print(); //2-3
    N2.print(); //0-0

    N2 = N1;

    N1.print(); //2-3
    N2.print(); //2-3

    N1.setA(12);

    N1.print(); //12-3
    N2.print(); //2-3,我想要N2的值仍然是2-3,而不是12-3,我希望通过拷贝构造函数将N1和N2分开
}

您的拷贝构造函数应该是正确的。问题在于赋值操作符N2 = N1; 不会调用拷贝构造函数,而是调用赋值操作符。为了实现深拷贝,您需要重载赋值操作符,使它执行深拷贝。以下是一个可能的实现:

Number& operator=(const Number& other) {
    if (this == &other) {
        return *this; // 避免自我赋值
    }

    delete a; // 释放旧的资源
    delete b;

    a = new int;
    b = new int;
    *a = *(other.a);
    *b = *(other.b);

    return *this;
}

这样,当执行N2 = N1;时,它将执行深拷贝,确保N2N1是两个独立的对象。

英文:

I'm beginner in C++ and I have a problem with my copy constructor: I need to do a deep copy, because my class has a pointers. I already defined a copy constructor and also I create an object N1(2,3) from my class Number. A second object N2 is intialized by using copy constructor.

But the copy constructor doesn't do a deep copy because, when I change the value of object N1, object N2 also has its values changed. I want to have two separate objects by using copy constructor.

My class Number:

   class Number
   {
   private:
	int* a;
	int* b;

    public:
	//default constructor:
	Number() {
		a = new int;
		b = new int;
		*a = 0;
		*b = 0;
	}
	
	//constructor with arguments:
	Number(int val1, int val2) {
		a = new int;
		b = new int;
		*a = val1; 
		*b = val2;
	}
	//copy constructor:
	Number(const Number&amp; other) {
		a = new int;
        b = new int;
       *a = *(other.a)
	   *b = *(other.b);
	}

	//getters and setters:
	int getA() {
		return *a;
	}
	int getB() {
		return *b;
	}
	void setA(int val) {
		*a = val;
	}
	void setB(int val) {
		*b = val;
	}

	//method print:
	void print() {
		cout &lt;&lt; &quot;value of a: &quot; &lt;&lt; *a &lt;&lt; &quot; value of b: &quot; &lt;&lt; *b &lt;&lt; endl;
	}
};

My main:

int main()
{
	Number N1(2,3), N2;

	N1.print(); //2-3
	N2.print(); //0-0

	N2 = N1;
	
	N1.print(); //2-3
	N2.print(); //2-3

	N1.setA(12);

	N1.print(); //12-3
	N2.print(); //12-3 i want object N2 have 2-3 values not 12-3 like N1
                           //i want to separate N1 from N2 by using copy constructor 
}

I'm trying to define this copy constructor but it's not working:

       //copy constructor:
	Number(const Number&amp; other) {
		a = new int;
        b = new int;
       *a = *(other.a)
	   *b = *(other.b);
	}

答案1

得分: 2

The issue you're seeing is lack of Complete Rule of 0/3/5.

And the fact that you are not invoking your copy constructor. You are invoking the assignment operator, which has been provided for you, and is shallow.

The line Number N1(2,3), N2; has declared N2 using the default constructor.

The line N2 = N1; then shallow assigns N1 because you didn't provide operator=().

If you wanted to invoke the copy constructor, you have to do so at the time of declaration. It is a constructor, after all.

Something like Number N2(N1).

In order to complete your code, you still need to write a destructor as well as an assignment operator. Then it's time to learn about move semantics.

英文:

The issue you're seeing is lack of Complete Rule of 0/3/5.

And the fact that you are not invoking your copy constructor. You are invoking the assignment operator, which has been provided for you, and is shallow.

The line Number N1(2,3), N2; has declared N2 using the default constructor.

The line N2 = N1; then shallow assignsN1 because you didn't provide operator=().

If you wanted to invoke the copy constructor, you have to do so at the time of declaration. It is a constructor, after all.

Something like Number N2(N1);.

In order to complete your code, you still need to write a destructor as well as assignment operator. Then it's time to learn about move semantics.

答案2

得分: 2

The code, N2 = N1;, does not invoke the copy constructor because N2 has already been constructed. Rather, it calls the assignment operator. As you have not provided a definition for that, the default is to make a shallow copy (i.e. just copy/overwrite the actual pointers, as you observe).

You need to define a deep-copying assignment operator; something like this:

    // assignment operator:
    Number& operator=(const Number& other) {
        *a = *(other.a);
        *b = *(other.b);
        return *this;
    }

Note, however, that were you to use the = N1 syntax in your declaration of N2 (as below), then that would call the copy constructor:

    Number N2 = N1; // This calls the copy constructor
英文:

The code, N2 = N1;, does not invoke the copy constructor because N2 has already been constructed. Rather, it calls the assignment operator. As you have not provided a definition for that, the default is to make a shallow copy (i.e. just copy/overwrite the actual pointers, as you observe).

You need to define a deep-copying assignment operator; something like this:

    // assignment operator:
    Number&amp; operator=(const Number&amp; other) {
        *a = *(other.a);
        *b = *(other.b);
        return *this;
    }

Note, however, that were you to use the = N1 syntax in your declaration of N2 (as below), then that would call the copy constructor:

    Number N2 = N1; // This calls the copy constructor

huangapple
  • 本文由 发表于 2023年2月8日 22:39:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75387374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定