0
#include <iostream>

using namespace std;

#define SELECT 0

class Z
{
    private:
        int *z1; int *z2;
    public:
        Z(const int x1 = 0, const int x2 = 0);
        Z(const Z &X);
        int *first (void) const {return z1;};
        int *second (void) const {return z2;};
        ~Z(void);
};

Z::Z(const int x1,const int x2){
    z1 = new int(x1);
    z2 = new int(x2);
}

#if SELECT == 1
Z::Z(const Z &X){
    z1 = new int(*X.first() );
    z2 = new int(*X.second() );
}
#else
Z::Z(const Z &X){
    z1 = X.first();
    z2 = X.second();
}
#endif

Z::~Z(){
    delete z1;
    delete z2;
}

int main()
{
 Z *zp;
    zp = new Z(3,5);
    Z  c(0,0);
    c = *zp;
    cout << "Content of c: " << *c.first() << " and " << *c.second() << endl;
    delete zp;
    cout << "Content of c: " << *c.first() << " and " << *c.second() << endl;
}

Hello, when I run this code, I get something like

Content of c: 3 and 5
Content of c: Garbage and Garbage

I was expecting this since, I am not creating another memory for c instead it points contents of zp. However, when I switch #define SELECT 1, now I am creating new memory for c. So when I delete zp, c still should point correct values (stored in different memory than zp) but what I get is still garbage shown below.

Content of c: 3 and 5
Content of c: Garbage and Garbage

Where is the problem?

I have another question. When I debug this in VScode, I get "Exception Occured. Unknown signal "for the lines

    delete z1;
    delete z2;

In CodeBlocks, there is no error. What is the problem?

Thanks for help.

1 Answers1

3

You don't follow the rule of three 1 2.

The copy constructor is only one part of the rule of three, but you also have to implement the copy assignment operator.

The c = *zp; does not call the copy constructor but the copy assignment operator, which is in your case the default one because you didn't specify any.

The default copy assignment operator will copy the pointers, so after c = *zp; both c and zp have the same pointers for z1 and z2 which will lead to a double free (that's most certainly the reason for your last question) of the memory initially allocated by zp and memory leaking for the memory allocated by c.

Z::Z(const Z &X){
    z1 = new int(*X.first() );
    z2 = new int(*X.second() );
}

Z& operator=(const Z& X)
{
  *z1 = *(X.z1);
  *z2 = *(X.z2);

  return *this;
}
t.niese
  • 39,256
  • 9
  • 74
  • 101