1

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& 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 << "value of a: " << *a << " value of b: " << *b << 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& other) {
        a = new int;
        b = new int;
       *a = *(other.a)
       *b = *(other.b);
    }

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Abdellah
  • 23
  • 4
  • `new int(*a = *(other.a))`?? Where did you pick up that syntax from? – UnholySheep Feb 08 '23 at 14:41
  • i already test that : Number(const Number& other) { a = new int; b = new int; *a = *(other.a); *b = *(other.b); } // but also this syntaxe not work – Abdellah Feb 08 '23 at 14:42
  • 2
    Also the correct solution would be to not dynamically allocate a single `int` as that makes no sense – UnholySheep Feb 08 '23 at 14:43
  • "i need to do a deep copy because my class has a pointers" no. If your class has pointers that should be not pointers then you need to get rid of the pointers. A missing deep-copy is only one of many issues in your code caused by pointless use of pointers. If this is "I want to practice pointers" ok, lesson to learn here: This is not a use case for pointers. – 463035818_is_not_an_ai Feb 08 '23 at 14:46
  • There is no need to first allocate, then assign. `a = new int(0);`, `a = new int(val1);`, `a = new int(*other.a);`. – molbdnilo Feb 08 '23 at 14:48
  • 2
    `N2 = N1;` calls the copy assignment operator, not the copy constructor. – interjay Feb 08 '23 at 14:50
  • 3
    *this syntax not work* - [The Definitive C++ Book Guide and List](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Evg Feb 08 '23 at 14:51
  • Your code never uses the copy constructor. – molbdnilo Feb 08 '23 at 14:52
  • how can i call the copy constructor? – Abdellah Feb 08 '23 at 14:53
  • important that you read this https://en.cppreference.com/w/cpp/language/rule_of_three – 463035818_is_not_an_ai Feb 08 '23 at 14:54
  • You don't call it; it's called behind your back when you initialize a new object as a copy of an original. Try `Number N1(2,3); Number N2(N1); N1.setA(12); N1.print(); N2.print();` – molbdnilo Feb 08 '23 at 14:55
  • @molbdnilo thank you i use this syntax Number N1(2,3); Number N2(N1); and it's work 100% – Abdellah Feb 08 '23 at 15:00

2 Answers2

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 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.

sweenish
  • 4,793
  • 3
  • 12
  • 23
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
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83