2

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?

JBL
  • 12,588
  • 4
  • 53
  • 84
zLeon
  • 137
  • 9
  • 2
    The code presented returns a reference to a local object that has ceased to exist. That's called a **dangling reference**. Using it in any way incurs Undefined Behavior. – Cheers and hth. - Alf Jul 24 '15 at 15:13
  • Sooner or later, you're going to find much of this: ["Operator Overloading"](https://stackoverflow.com/questions/4421706/operator-overloading) helpful in knowing when to return references, when to return copies and rely on RVO, when to use free-functions vs member-functions, etc. I thus advise you take some time to review it. – WhozCraig Jul 24 '15 at 15:19
  • "What is the objective of returning by reference in operation overloading" Premature optimization. And the harmful kind on top of that – KABoissonneault Jul 24 '15 at 15:20

2 Answers2

8

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 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • From what I understand , I'm returning the memory address of resvec which is a local object and which is destroyed very soon and has no other purposes , therefore it can lead to error proned program., – zLeon Jul 24 '15 at 15:39
  • @zLeon You are right. Internally references are represented like pointers. The stack memory used by the function after exiting it can be used by some other function as for example by the operator << used in statement cout< – Vlad from Moscow Jul 24 '15 at 15:42
3

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.

Jack
  • 131,802
  • 30
  • 241
  • 343