Reputation: 4990
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
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
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
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