I am learning operator overloading. I am trying to overload + operator in my code. When I am returning with implicit de-referencing, the output is gibberish.
If I explicit de-reference the variable when returning, it is working properly. Is the issue happening because I am referencing some temporary variable and it is destroyed, after coming out of the scope. If so, then why is explicit de-reference working? P.S. : I am aware that I can return without reference and I am not following rule of 3 in the code.
class ComplexNum
{
private:
int real, imaginary;
public:
ComplexNum();
ComplexNum(int x, int y);
ComplexNum(const ComplexNum& other);
~ComplexNum();
int getReal() const;
int getImaginary() const;
const ComplexNum& operator=(const ComplexNum&);
friend std::ostream& operator <<(std::ostream& out, const ComplexNum& a);
ComplexNum& operator+(const ComplexNum&);
};
ComplexNum::ComplexNum()
{
}
ComplexNum::ComplexNum(int x, int y):real(x), imaginary(y)
{
}
ComplexNum::ComplexNum(const ComplexNum& other)
{
this->real = other.real;
this->imaginary = other.imaginary;
}
ComplexNum::~ComplexNum()
{
}
int ComplexNum::getReal() const
{
return real;
}
int ComplexNum::getImaginary() const
{
return this->imaginary;
}
const ComplexNum& ComplexNum::operator=(const ComplexNum& other)
{
real = other.real;
imaginary = other.imaginary;
return *this;
}
ComplexNum& ComplexNum::operator+(const ComplexNum& other)
{
ComplexNum a(real + other.getReal(), imaginary + other.getImaginary());
return a;
}
/*the above one doesn't work but the below commented out works fine.*/
/*
ComplexNum& ComplexNum::operator+(const ComplexNum& other)
{
ComplexNum* a = new ComplexNum(real + other.getReal(), imaginary + other.getImaginary());
return *a;
}*/
std::ostream& operator<<(std::ostream& out,const ComplexNum& a)
{
out << a.real << " & " << a.imaginary << "j";
return out;
}
/*Here is how I am calling it in main*/
int main()
{
ComplexNum complex(3, 4);
ComplexNum c2(5, 6);
cout << c2 << endl;
ComplexNum& c3 = c2 + complex;
/*getting error in the below code. c3 is o/p gibberish value as if not initialized*/
cout << c3<< " " << c2 << endl;
return 0;
}
I am getting gibberish value, as if the the variable c3 is not initialized.
This code here causes a memory leak, because the pointer a
is automatically deleted once the end of scope is reached and you have no way to delete the memory allocated in the heap by new
. Unluckily for you, you dereferenced a
right before it got deleted in the return
statement, and you were able to access its' value, thinking that everything was alright.
ComplexNum& ComplexNum::operator+(const ComplexNum& other)
{
ComplexNum* a = new ComplexNum(real + other.getReal(), imaginary + other.getImaginary());
return *a;
}
To be honest, most of the code you have can be elided by using the = default
specifier or not having them at all. Use it because it makes the code easy to read.
Operators that are used to return a new instance of the class (ex. +,-,*,/
), should not be returned by reference. Operators that modify the current instance of the class (ex. =,+=,-=,*=,/=
), should be returned by reference.
#include <iostream>
struct ComplexNum
{
int real;
int imaginary;
ComplexNum() = default;
ComplexNum(int x, int y) : real(x), imaginary(y)
{;}
friend std::ostream& operator <<(std::ostream& out, const ComplexNum& a)
{
out << a.real << " & " << a.imaginary << "j";
return out;
}
ComplexNum operator + (const ComplexNum &other)
{
int r = this->real + other.real;
int i = this->imaginary + other.imaginary;
return ComplexNum(r,i);
}
ComplexNum& operator += (const ComplexNum &other)
{
this->real += other.real;
this->imaginary += other.imaginary;
return *this;
}
~ComplexNum() = default;
};
int main()
{
ComplexNum c1(3, 4);
std::cout << c1 << std::endl;
ComplexNum c2(5, 6);
std::cout << c2 << std::endl;
ComplexNum c3 = c1 + c2;
std::cout << c3 << std::endl;
c3 += c1;
std::cout << c3 << std::endl;
}
Results:
3 & 4j
5 & 6j
8 & 10j
11 & 14j
Online code example: https://rextester.com/QNR88316