Search code examples
c++referencereturnoperator-overloadingthis

Return result by reference in C++


I was practicing something in C++, and I ran into a task which I can solve, but I was curious about this code below. I don't know why we return our values by reference in these two functions:

fraction& operator+=(fraction);
fraction& operator++();

#include <iostream>
using namespace std;

class fraction
{
private:
    int br;
    int im;
public:
    fraction(int=0,int=1);
    fraction& operator+=(fraction);
    fraction& operator++();
    fraction operator++(int);
    void print(){cout<<br<<"/"<<im<<endl;}
};

fraction::fraction(int a,int b):br(a),im(b){}

fraction& fraction::operator+=(fraction r)
{
    br = br*r.im + im*r.br;
    im = im*r.im;
    return *this;
}

fraction& fraction::operator++()
{
    return (*this)+=1;
}

fraction fraction::operator++(int i)
{
    fraction pom(*this);
    (*this)+=1;
    return pom;
}

int main()
{
    cout<<"Type in the values for fractions"<<endl;
    int b,i;
    cin>>b>>i;
    fraction r1(b,i);
    cin>>b>>i;
    fraction r2(b,i);
    r1+=(r2++);
    r1.print();
}

Then I tried to remove the & in these functions, and that code also worked fine:

#include <iostream>
using namespace std;

class fraction
{
private:
    int br;
    int im;
public:
    fraction(int=0,int=1);
    fraction operator+=(fraction);
    fraction operator++();
    fraction operator++(int);
    void print(){cout<<br<<"/"<<im<<endl;}
};

fraction::fraction(int a,int b):br(a),im(b){}

fraction fraction::operator+=(fraction r)
{
    br = br*r.im + im*r.br;
    im = im*r.im;
    return *this;
}

fraction fraction::operator++()
{
    return (*this)+=1;
}

fraction fraction::operator++(int i)
{
    fraction pom(*this);
    (*this)+=1;
    return pom;
}

int main()
{
    cout<<"Type in the values for fractions"<<endl;
    int b,i;
    cin>>b>>i;
    fraction r1(b,i);
    cin>>b>>i;
    fraction r2(b,i);
    r1+=(r2++);
    r1.print();
}

So, my question is, why do we use & in the first code?

Also, I would appreciate if you could tell me why this code doesn't work. It's a combination of the two codes above, where I removed & only from one function.

#include <iostream>
using namespace std;

class fraction
{
private:
    int br;
    int im;
public:
    fraction(int=0,int=1);
    fraction operator+=(fraction);
    fraction& operator++();
    fraction operator++(int);
    void print(){cout<<br<<"/"<<im<<endl;}
};

fraction::fraction(int a,int b):br(a),im(b){}

fraction fraction::operator+=(fraction r)
{
    br = br*r.im + im*r.br;
    im = im*r.im;
    return *this;
}

fraction& fraction::operator++()
{
    return (*this)+=1;
}

fraction fraction::operator++(int i)
{
    fraction pom(*this);
    (*this)+=1;
    return pom;
}

int main()
{
    cout<<"Type in the values for fractions"<<endl;
    int b,i;
    cin>>b>>i;
    fraction r1(b,i);
    cin>>b>>i;
    fraction r2(b,i);
    r1+=(r2++);
    r1.print();
}

Sorry for the noob questions, but I just started practicing in C++, and I spent hours trying to figure this out.


Solution

  • So, my question is, why do we use & in the first code?

    & are used for performance and conformance reasons. Both operators (pre-increment operator ++ and assignment operator+=) from their assumption modify provided value. E.g.:

    int i=5;
    std::cout << ++i; // This will print 6. Notice there is no more value 5, even here
    std::cout << i;   // This will print 6 also.
    

    Since the original value is lost, there is no point for creating new object and destroy current one. Just current object can be reused for providing new value.

    I would recommend looking into reference when overloading operators, since it is easy to create own version that has performance loss or doesn't work with const objects. Here are some links.

    Also, I would appreciate if you could tell me why this code doesn't work. It's a combination of the two codes above, where I removed & only from one function.

    This one is a little more tricky. If you take closer look at the code from third example:

    fraction fraction::operator+=(fraction r)
    {
        br = br*r.im + im*r.br;
        im = im*r.im;
        return *this;
    }
    
    fraction& fraction::operator++()
    {
        return (*this)+=1;
    }
    

    You will notice that operator++ is using operator+= inside. In fact operator++ is returning what operator+= returns, so operator++ is returning reference to local fraction object that is destroyed when operator++ ends. You get reference to just destroyed object. This is bad and this is reason why it doesn't work.