#include <iostream>
using namespace std;
class Exem {
int *a;
public:
Exem() { a = new int; *a = 0; };
Exem (int x) { a = new int; *a = x; };
~Exem () { delete a; };
int f (void);
Exem operator+ (Exem);
};
int Exem::f (void) {
return *a * 2;
}
Exem Exem::operator+ (Exem nimda) {
Exem aux;
*aux.a = *a + *nimda.a;
return aux;
}
int main() {
Exem adabo(1);
Exem inakos(2);
adabo = adabo + inakos;
cout << adabo.f();
cin.get();
}
This is my code, an example class made to showcase the problem. The output of main() would, in theory, be ‘6’, but all that actually shows up are nonsensical numbers.
This apparently has to do with the class’ destructor, which, from what I understood, get called too early at the end of the operator+ function – aux gets lost before it is actually passed. I came to such conclusion because ~Exem(), when commented, allows the program to execute as expected.
I’m guessing this has to do with these two compilers, because when I tried to compile the exact same code in Embarcadero RAD Studio it would work.
You need to explicitly define a copy constructor and assignment operator for
Exemas you have a dynamically allocated member variable.If a copy constructor and assignment operator are not explicitly defined for a class the compiler generates default versions of these, which are not suitable for a class that has dynamically allocated members. The reason the default generated versions are unsuitable is that they perform a shallow copy of the members. In the case of
Exem, when an instance of it is copied more than one instance ofExemis pointing to the same dynamically allocatedintmember nameda. When one of the instances is destroyed thatadeleted, and leaves the other instance with a dangling pointer and undefined behaviour.See the rule of three.
A simple fix for
Exemwould be changeafrom anint*to anint. The default copy constructor, assignment operator and destructor would be correct.Note that
Exem::operator+()should take aconst Exem¶meter as it does not change its argument.