Slazer
Slazer

Reputation: 4990

Return value of operator<< function

I understand I should return "ostream&" from "operator<<" to be able to "chain" the operator like this

cout<<a<<b<<c;

In the following code, however, I do not return the "ostream&" and the chaining is still possible. Why?

#include <iostream>
using namespace std;

class CComplexNumber{
    float m_realPart;
    float m_imagPart;
public:
    CComplexNumber(float r,float i):m_realPart(r),m_imagPart(i){}

    friend ostream& operator<<(ostream& lhs,CComplexNumber rhs){
        lhs<<"["<<rhs.m_realPart<<","<<rhs.m_imagPart<<"]"<<endl;
        //MISSING RETURN STATEMENT!
    }
};

int main() {
    CComplexNumber a(1,2);
    CComplexNumber b(3,4);
    CComplexNumber c(5,6);

    cout<<a<<b<<c;

    return 0;
}

OUTPUT

[1,2]
[3,4]
[5,6]

Upvotes: 3

Views: 148

Answers (3)

Mats Petersson
Mats Petersson

Reputation: 129464

It's "pure luck". The return value from a function is in a particular register. Since your existing code already calls an operator<<, it returns the right thing for you, so as long as no other code is involved AFTER that point, you're getting the return value from the internal level of operator<<. Add a std::string s = "xyz";" (and use s somewhere in the code), and it will probably break, because the destructor for std::string called at the end of the function "destroys" the return value from the operator<<. So relying on this is very dangerous, as innocuous changes will cause it to "fall over".

Upvotes: 1

zindorsky
zindorsky

Reputation: 1592

As others have pointed out, you have invoked Undefined Behavior: anything can happen. If you're lucky, you get a crash. Looks like you weren't lucky.

If you're interested as to why it happened to work in this case, you should look at the generated assembly. My off the cuff guess would be that a pointer to lhs was left in the register that returns values on your platform. And since references in C++ are usually implemented with pointers, that would have the same effect as returning a ref to lhs.

But this is a complete stab in the dark, and in the end not very interesting or important. Just listen to your compiler's warnings and Don't Do That.

Upvotes: 3

Mark B
Mark B

Reputation: 96281

Falling off the end of a non-void function is undefined behavior. One possible undefined behavior is working as you'd expect it to were the return in place.

g++ offers a handy warning to prevent this from ever happening to you.

Upvotes: 8

Related Questions