zLeon
zLeon

Reputation: 137

What is the purpose of returning by reference in C++ functions?

My question is about returning by reference in a function. For example , I have the code:

main.cpp

class Vector{
public:
    Vector(int a , int b){
        x = a;
        y= b;
    }

    Vector() { }

    int x = 1;
    int y = 1;
};

Vector& operator+(const Vector& lvec ,const Vector& rvec ){
    Vector resvec;
    resvec.x = lvec.x + rvec.x;
    resvec.y = lvec.y + rvec.y;
    return resvec;
}

int main(){
    Vector vecone(1,2);
    Vector vectwo(1,2);
    Vector resultvec = vecone + vectwo;
    cout<<endl<<"X:"<<resultvec.x<<endl<<"Y:"<<resultvec.y;
}

It runs and works very well, however , I don't seem to understand the purpose of the reference operator ( & ) in the operator overloading function , yet i've seen it in many source code's containing operator overloading functions. The program seems to run very well when I dismiss the operator, so my question is - what's the purpose of returning by reference in a funcion? and does it serve a special objective in the code I presented?

Upvotes: 2

Views: 124

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 310920

This definition of the operator

Vector& operator+(const Vector& lvec ,const Vector& rvec ){
Vector resvec;
resvec.x = lvec.x + rvec.x;
resvec.y = lvec.y + rvec.y;
return resvec;
}

is wrong. It returns a reference to local object resvec that will be destroyed after the control will exit the function. So the reference will be invalid and as result the program has undefined behaviour.

A correct definition can look like

Vector operator +( const Vector& lvec , const Vector& rvec )
{
    return { lvec.x + rvec.x, lvec.y + rvec.y };
}

Or like

Vector operator +( const Vector& lvec , const Vector& rvec )
{
    return Vector( lvec.x + rvec.x, lvec.y + rvec.y );
}

Or returned type can be declared like const Vector

Nevertheless a reference as the return type is used very often especially in the declaration of the subscript operator

Consider for example

Here is a demonstrative program

#include <iostream>

class Vector
{
public:
    Vector( int a , int b ) : x( a ), y( b )
    {
    }

    Vector() : x( 0 ), y( 0 )
    { 
    }

    size_t size() const { return 2; }

    int & operator []( size_t i ) { return i == 0 ? x : y; }
    int operator []( size_t i ) const { return i == 0 ? x : y; }

private:
    int x;
    int y;
};

int main() 
{
    Vector v( 10, 20 );

    for ( size_t i = 0; i < v.size(); i++ ) std::cout << v[i] << ' ';
    std::cout << std::endl;

    for ( size_t i = 0; i < v.size(); i++ ) ++v[i];

    for ( size_t i = 0; i < v.size(); i++ ) std::cout << v[i] << ' ';
    std::cout << std::endl;
}

Its output is

10 20 
11 21 

Upvotes: 8

Jack
Jack

Reputation: 133557

The point is that operator+ must be overloaded in a way that is proper to its functionality according to the language syntax.

When you have (a + b) + c the subexpression (a + b) should return a temporary value which is then added to c. So returning a reference makes no sense since a + b should generate a new value which is distinguished from others.

Indeed you could return a reference to

  • an existing object, which is semantically wrong since it means you are mutating something when + binary operator shouldn't.
  • a temporary object, but returning a reference to a temporary object will leave you just a dangling reference (and that's your case)

That's why usually operator+ should return aT, not a T&. The situation is the opposite with operators like operator+= or operator++ which indeed mutate the state of the object are called on, so returning a reference is the right choice in that situation.

Upvotes: 3

Related Questions