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

hmjd
  • 120,187
  • 20
  • 207
  • 252
Mutoh
  • 358
  • 3
  • 18

1 Answers1

2

You need to explicitly define a copy constructor and assignment operator for Exem as 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 of Exem is pointing to the same dynamically allocated int member named a. When one of the instances is destroyed that a deleted, and leaves the other instance with a dangling pointer and undefined behaviour.

See the rule of three.

A simple fix for Exem would be change a from an int* to an int. The default copy constructor, assignment operator and destructor would be correct.


Note that Exem::operator+() should take a const Exem& parameter as it does not change its argument.

Community
  • 1
  • 1
hmjd
  • 120,187
  • 20
  • 207
  • 252