1

I can't figure out what is the problem with my C++ class (using Visual Studio). Visual Studio is not giving any desired output, just saying " exited with code -1073741819". I created a class named Complex using raw pointers, when no-args or parameterized constructor is called, memory is allocated using new int and when variable goes out of scope, destructor deallocates memory using delete keywords. The only problem i am facing is that, my + operator overloading causing problem and i am pretty sure that this problem is related to destructor, when i remove destructor code, + operator works just fine. Or when I don't use + operator, also then program works fine. Please help me by figuring out code. Please don't say to me that "you don't need raw pointers here", actually i have been told to do so (using only pointers). I am stuck on this for many hours.
Here is my code, please go through it , including + operator overloading code and destructor code.

#include<iostream>
using namespace std;

class Complex {
private:
    int *real;
    int *complex;
    
public:
    // some declarations
    Complex();
    Complex(int, int);
    Complex(const Complex& source);
    Complex operator+ (const Complex& rhs);
    Complex& operator= (const Complex& rhs);
    void disp() {
        cout << "(" << *real << "," << *complex << ")" << endl;
    }
    // destructor
    ~Complex() {
        delete real;
        real = nullptr;
        delete complex;
        complex = nullptr;
    }
    
};

// no-args constructor
Complex::Complex() {
    real = new int;
    *real = 0;
    complex = new int;
    *complex = 0;
}
// parameterized constructor
Complex::Complex(int x, int y) : Complex() {

    *real = x;
    *complex = y;
}
//copy constructor
Complex::Complex(const Complex& source) {
    *(this->real) = *(source.real);
    *(this->complex) = *(source.complex);
}

// overloading + operator
Complex Complex::operator+ (const Complex &rhs) {
    int a, b;
    a = *(this->real) + *(rhs.real);
    b = *(this->complex) + *(rhs.complex);
    Complex temp(a,b);
    return temp;
}
// overloading = operator
Complex& Complex::operator= (const Complex& rhs) {
    
    *(this->real) = *(rhs.real);
    *(this->complex) = *(rhs.complex);
    return *this;

}

int main() {
    Complex n1(5,-9);
    Complex n2(5,-1);
    Complex n3;
    n3=n1 + n2;
    n3.disp();
    
    return 0;
}
wm 50
  • 27
  • 6
  • I get "`(10,-10)`" on Xcode . is that expected ? – puio Aug 28 '20 at 06:24
  • yes u r ri8, but visual studio is not producing this output. I belive that visual studio best catches deep errors, other compilers ignore small errors. VS helps in improving these errors. VS is not giving correct ans – wm 50 Aug 28 '20 at 06:28
  • Since you're managing memory yourself in a class, i.e. allocating memory on heap that will not get freed automatically, you need to follow rule of three or rule of five. (I guess) - https://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11 - https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three Try deleting some default constructors. – puio Aug 28 '20 at 06:31

2 Answers2

2

You don't allocate any memory in your copy constructor, so your assignments happen to uninitialized memory.

Complex::Complex(const Complex& source) {
    *(this->real) = *(source.real);
    *(this->complex) = *(source.complex);
}

If I change it to this:

Complex::Complex(const Complex& source) : Complex() {
    *(this->real) = *(source.real);
    *(this->complex) = *(source.complex);
}

Your program outputs (10,-10)

EDIT: Question in the comments.

I have added a few printouts to your program to show exactly what is going on:

#include<iostream>
using namespace std;

class Complex {
private:
    int* real;
    int* complex;

public:
    // some declarations
    Complex();
    Complex(int, int);
    Complex(const Complex& source);
    Complex operator+ (const Complex& rhs);
    Complex& operator= (const Complex& rhs);
    void disp() {
        cout << "(" << *real << "," << *complex << ")" << endl;
    }
    // destructor
    ~Complex() {
        std::cout << "destructor" << std::endl;
        delete real;
        real = nullptr;
        delete complex;
        complex = nullptr;
    }
};

// no-args constructor
Complex::Complex() {
    std::cout << "constructor" << std::endl;
    real = new int;
    *real = 0;
    complex = new int;
    *complex = 0;
}
// parameterized constructor
Complex::Complex(int x, int y) : Complex() {

    std::cout << "(x,y)constructor" << std::endl;
    *real = x;
    *complex = y;
}
//copy constructor
Complex::Complex(const Complex& source) : Complex() {
    std::cout << "copy constructor" << std::endl;
    *(this->real) = *(source.real);
    *(this->complex) = *(source.complex);
}

// overloading + operator
Complex Complex::operator+ (const Complex& rhs) {
    std::cout << "op+" << std::endl;
    int a, b;
    a = *(this->real) + *(rhs.real);
    b = *(this->complex) + *(rhs.complex);
    Complex temp(a, b);
    return temp;
}
// overloading = operator
Complex& Complex::operator= (const Complex& rhs) {
    std::cout << "op=" << std::endl;
    *(this->real) = *(rhs.real);
    *(this->complex) = *(rhs.complex);
    return *this;

}

int main() {
    Complex n1(5, -9);
    Complex n2(5, -1);
    Complex n3;
    n3 = n1 + n2;
    n3.disp();

    return 0;
}

Now running your program results this:

constructor
(x,y)constructor
constructor
(x,y)constructor
constructor
op+
constructor
(x,y)constructor
constructor
copy constructor
destructor
op=
destructor
(10,-10)
destructor
destructor
destructor

As you can see, there is a "copy constructor" in there. Specifically this line: n3 = n1 + n2; results in this printout:

op+               // n1 + n2
constructor       // base constructor from param constructor
(x,y)constructor  // constructing the return value: Complex temp(a, b);
constructor       // base constructor from copy constructor
copy constructor  // copying from temp to the return value
destructor        // destroying temp
op=               // assigning the return value to n3
destructor        // destroying the return value

Do note btw, that this was compiled in debug mode. If I compile in release mode the output changes:

constructor
(x,y)constructor
constructor
(x,y)constructor
constructor
op+
constructor
(x,y)constructor
op=
destructor
(10,-10)
destructor
destructor
destructor

The pertinent point here is that the compiler managed to optimize out the copy constructor, by recognizing that there is no point in constructing temp only to then copy and destroy it. But this only happens when optimization is turned on.

Frodyne
  • 3,547
  • 6
  • 16
  • thank u, but can you tell me one thing? Without using copy constructor my program is giving runtime error, why is it so? I m not even using copy constructor through my program, as you can see, i created Complex n3, not apparently any work of copy constructor, then i used n3=n1+n2, here overloaded = operator is doing its work, again there is no apparent work of copy constructor. Then why program crashes? – wm 50 Aug 28 '20 at 06:45
  • @wm50 I added an edit which hopefully answers your question. – Frodyne Aug 28 '20 at 07:03
  • Thank u soo much for great explanation – wm 50 Aug 28 '20 at 07:23
0

I'm suspecting that your parameterized constructor is the problem... In your parameterized constructor, you are creating a Complex class object, which takes the *real and *complex pointers, pointing it to the passed in integers(x and y). No memory is allocated hence when your program ends, your destructor gets called and attempts to deallocate memory inside n1 and n2 that were never dynamically allocated.

I haven't touched C++ in a few months, so I could be wrong. Feel free to check and get back to me on your results.

Nii N.
  • 11
  • 1