Thread: importance of returning reference in operator overloading.

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    40

    importance of returning reference in operator overloading.

    Hi all,

    I would like to know the "importance of returning reference in operator overloading." I searched on internet, even I could understand it but not able to digest it. there is some concept like operator chaining. If overloaded operator wont return reference, we could not perform chained operation with user defined data type like class sample

    create three object sample t = a+b+c;
    but I tried with and without "retrun reference" of operator+().It was working fine
    not what is the use of returning reference from overloaded operator.

    can somebody explain me with an example?

    I tried with ostream and istream overloaded, for that compiler is restricting & in retrun value. IF I remove it I am getting compilation error.

    Please explain on this.

    Your help will be highly appreciated

    Thansk in Advance,
    Vaibhav

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Since the usual semantics of operator+ involves returning a new object that is the "sum" of the two arguments, returning by reference is usually wrong.

    On the other hand, the usual semantics of operator+= involves returning the left hand side object, hence returning by reference is usually correct to avoid an unnecessary copy should there be operator chaining.

    std::istream and std::ostream are not copyable, so trying to return objects of those types by value is wrong, as your compiler has noted.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    40
    can somebody explain with an example?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by vaibhavs17
    can somebody explain with an example?
    I am not sure what is the explanation that you are looking for, but an example of operator chaining:
    Code:
    #include <iostream>
    
    class Integer
    {
    public:
        Integer(int n = 0) : n(n) {}
    
        Integer& operator+=(const Integer& other)
        {
            n += other.n;
            return *this;
        }
    
        friend std::ostream& operator<<(std::ostream& out, const Integer& i)
        {
            return out << i.n;
        }
    private:
        int n;
    };
    
    int main()
    {
        Integer x(1);
        Integer y(2);
        Integer z(3);
        x += y += z;
        std::cout << x << std::endl << y << std::endl << z << std::endl;
    }
    Notice that the value of y that is printed is the sum of the initial y and z, but the value of x that is printed is the sum of the initial values of all three Integer objects.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Mar 2009
    Posts
    40
    Thanks Laserlight,

    But I have one doubt, if you remove the & from
    Integer& operator+=(const Integer& other)

    does it impact anything?
    It will work the same, so now my question is what is use of returning reference from overloaded operator? It is not related with operator chaining.
    May be I am not able to digest it.
    Please explain. Thanks for efforts.
    Please check below code, I removed & from both overloaded function, it is still working fine
    Code:
    #include <iostream>
    
    class Integer
    {
    public:
        Integer(int n = 0) : n(n) {}
    
        Integer operator+=(const Integer& other)
        {
            n += other.n;
            return *this;
        }
    
        friend std::ostream operator<<(std::ostream& out, const Integer& i)
        {
            return out << i.n;
        }
    private:
        int n;
    };
    
    int main()
    {
        Integer x(1);
        Integer y(2);
        Integer z(3);
        x += y += z;
        std::cout << x << std::endl << y << std::endl << z << std::endl;
    }
    Quote Originally Posted by laserlight View Post
    I am not sure what is the explanation that you are looking for, but an example of operator chaining:
    Code:
    #include <iostream>
    
    class Integer
    {
    public:
        Integer(int n = 0) : n(n) {}
    
        Integer& operator+=(const Integer& other)
        {
            n += other.n;
            return *this;
        }
    
        friend std::ostream& operator<<(std::ostream& out, const Integer& i)
        {
            return out << i.n;
        }
    private:
        int n;
    };
    
    int main()
    {
        Integer x(1);
        Integer y(2);
        Integer z(3);
        x += y += z;
        std::cout << x << std::endl << y << std::endl << z << std::endl;
    }
    Notice that the value of y that is printed is the sum of the initial y and z, but the value of x that is printed is the sum of the initial values of all three Integer objects.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by vaibhavs17 View Post
    Thanks Laserlight,

    But I have one doubt, if you remove the & from
    Integer& operator+=(const Integer& other)

    does it impact anything?
    Yes. It would cause the following code to not work as you might expect:

    Code:
    (a += 1) += 2;
    The expected result would be to add 3 to the value of a. But if operator+=() returns an object instead of a reference, it will actually only add 1 to the value, because the result of the first increment is not the original object but a temporary copy of it -- the 2 gets added to this temporary then silently vanishes.

    It's not absolutely wrong one way or the other, but the general rule is that when overloading an operator, its meaning and behavior should be what the programmer would expect with "natural" operators.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Most likely the return value of += is just ignored. If you return by value, an object needs to be constructed (and destructed immediately) - assuming no optimization.

    Code:
    a += b; //result ignored
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by vaibhavs17
    But I have one doubt, if you remove the & from
    Integer& operator+=(const Integer& other)

    does it impact anything?
    Maybe, maybe not.

    Quote Originally Posted by vaibhavs17
    It will work the same, so now my question is what is use of returning reference from overloaded operator? It is not related with operator chaining.
    As I stated: the usual semantics of operator+= involves returning the left hand side object, hence returning by reference is usually correct to avoid an unnecessary copy should there be operator chaining.

    For example:
    Code:
    #include <iostream>
    
    class Integer
    {
    public:
        Integer(int n = 0) : n(n) {}
    
        Integer(const Integer& other) : n(other.n)
        {
            std::cout << "copy ctor" << std::endl;
        }
    
        Integer operator+=(const Integer& other)
        {
            n += other.n;
            return *this;
        }
    
        friend std::ostream& operator<<(std::ostream& out, const Integer& i)
        {
            return out << i.n;
        }
    private:
        int n;
    };
    
    int main()
    {
        Integer x(1);
        Integer y(2);
        Integer z(3);
        x += y += z;
        std::cout << x << std::endl << y << std::endl << z << std::endl;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    40
    good catch!

    well I was just wanted to know usage of & there.
    you both cleared my doubt now.

    can you explain with ostream?

    i remaoved & there also.
    What would impact on that?
    with an example.

    Thanks a lot!
    Vaibhav

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by brewbuck
    It would cause the following code to not work as you might expect:
    That said, there is a case to be made for returning by const reference instead of the canonical return by non-const reference to disable such unusual syntax.

    Quote Originally Posted by vaibhavs17
    can you explain with ostream?

    i remaoved & there also.
    What would impact on that?
    with an example.
    Why don't you post your example?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by laserlight View Post
    That said, there is a case to be made for returning by const reference instead of the canonical return by non-const reference to disable such unusual syntax.
    Yes. But in that situation, attempting an expression like (a += 1) += 2 would raise a compile error instead of silently compiling to do something you may not have anticipated.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #12
    Registered User
    Join Date
    Mar 2009
    Posts
    40
    Hi,
    Please check my example
    I tried with below code for istream and ostream.

    If I tries to remove &, I was getting error.

    Code:
    //One case where friend function becomes necassary
    #include<iostream.h>
    class emp
    {
    	int age;
    	float salary;
    	char name[20];
    public:
    
    	friend ostream& operator<<(ostream& o, emp& e);
    	friend istream& operator>>(istream& i, emp& e);
    };
    
    ostream& operator<<(ostream&o, emp& e)
    {
    	o<<endl<<e.name<<endl<<e.age<<endl<<e.salary<<endl;
    	return o;
    }
    
    istream& operator>>(istream& i, emp& e)
    {
    	i>>e.name>>e.age>>e.salary;
    	return i;
    }
    
    void main()
    {
    	emp e;
    	cout<<"Enter name agfe salary of the employee"<<endl;
    	cin>>e;
    	cout<<e;
    
    }

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Quote Originally Posted by vaibhavs17
    Please check my example
    I tried with below code for istream and ostream.

    If I tries to remove &, I was getting error.
    I already told you: std::istream and std::ostream are not copyable, so trying to return objects of those types by value is wrong, as your compiler has noted.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by laserlight View Post
    I already told you: std::istream and std::ostream are not copyable, so trying to return objects of those types by value is wrong, as your compiler has noted.
    By "not copyable," we mean that these classes have placed the copy constructor and assignment operator in the "private" region of their definition, deliberately making these inaccessible.

    It does not make sense to copy an open file, since this would imply re-opening the file, something you probably don't want.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  15. #15
    Registered User
    Join Date
    Mar 2009
    Posts
    40
    why compiler did not flash error for your piece of code without &.

    Code:
      friend std::ostream operator<<(std::ostream& out, const Integer& i)
        {
            return out << i.n;
        }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. C OpenGL Compiler Error?
    By Matt3000 in forum C Programming
    Replies: 12
    Last Post: 07-07-2006, 04:42 PM
  5. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM