I was reading an article about Overloading the Stream Insertion Operator (<<). It stresses that the output stream object ought to be returned to ensure the operator is cascaded correctly. But it seems without the return, the output is still correct, what's wrong here?
#include<iostream>
class Rational
{
friend std::ostream& operator<<(std::ostream&, const Rational&);
private:
int numerator;
int denominator;
public:
Rational(int num, int den): numerator{num}, denominator{den} {}
};
std::ostream& operator<<(std::ostream& lhs, const Rational& rhs)
{
lhs << rhs.numerator << "/" << rhs.denominator;
//return lhs;
}
int main()
{
Rational r1(3, 5);
std::cout << "The value of r1 is " << r1 << std::endl; // After commenting return lhs; still works fine
}
This is UB, for a function that is supposed to return an object ends without a return statement. It might work well but nothing is guaranteed.
From the standard, $6.6.3/2 The return statement [stmt.return]:
(emphasis mine)
Flowing off the end of a constructor, a destructor, or a function with a cv
void
return type is equivalent to areturn
with no operand. Otherwise, flowing off the end of a function other thanmain
(basic.start.main) results in undefined behavior.
You might want to see the result from clang; which gives a warning
warning: control reaches end of non-void function [-Wreturn-type]
and results in an infinite recursion.