Overloading << operator and recursion
Asked Answered
O

2

5

I tried the following code:

#include <iostream>
using std::cout;
using std::ostream;

class X
{
public:
    friend ostream& operator<<(ostream &os, const X& obj) 
    {
        cout << "hehe";          // comment this and infinite loop is gone
        return (os << obj);
    }
};

int main()
{
    X x;
    cout << x;
    return 0;
}

When I compile & run this, it's as expected; an infinite loop. If I remove the cout statement inside the friend function, the recursion doesn't happen. Why is it so?

Obbard answered 1/3, 2010 at 10:58 Comment(5)
Am using MinGW (Minimalist GNU for Windows) btw.Obbard
How do you notice the recursion doesn't happen? Does it end the program properly? Or does it just not print anything and you have to terminate it? (Notice that tail recursion may make it you don't receive a stack overflow).Postdoctoral
@litb: It immeditely fell back to the terminal (I didn't press a single key to kill the process).Obbard
@litb: I tried running the binary via gdb and it says a SIGSEGV :) Thanks for the comment, probably you should write it as an answer! It's crashing by a stack overflow!! Yay!Obbard
Being this question about stack overflow, I think that it should definitely go to meta.Witty
N
7

Optimizer decides all your remaining activity has no effect and optimizes it away. Whether it's right or wrong is a different matter.

In particular:

X x;

creates empty object "x"

cout << x;

calls:

return (os << obj);

which is appending empty object; the compiler notices 'os' hasn't grown any since the last call and shows no promise doing so any further (and nothing else happens) so it decides the whole business is redundant and can be truncated at this point.

In case you call

    cout << "hehe";          // comment this and infinite loop is gone

there is some extra activity so the optimizer doesn't remove the following call.

I guess if you initialized x with anything non-empty, or performed any non-null activity other than cout << "hehe";, you'd have recursion running just the same.

Nictitate answered 1/3, 2010 at 11:6 Comment(3)
Actually I think that the optimizer would be perfectly right if the standard specified that infinite recursion causes "undefined behavior"; doing nothing at all would be OK in that case. I can't find a copy of the C++ standard on the net, can anyone who have it check?Witty
...on unrelated note, I wonder what if the call was enclosed in try-catch(...) to capture stack overflow exception. Which, I think, would be pretty much the expected behavior, correct me if I'm wrong.Nictitate
I don't think that such exception (that, by the way, is not a C++ exception, but it's some kind of signal on *NIX and a SEH exception on Windows) can be caught. Actually, there's nothing you can do when the stack overflows: everything has already gone nuts. If you notice, Windows applications that go in stack overflow do not even display an error message, because they can't do anything now that there's no more stack.Witty
L
6

In both cases (with and without writing "hehe") Visual Studio 2005 gives the following warning:

warning C4717: 'operator<<' : recursive on all control paths, function will cause runtime stack overflow

In both cases it compiles and in both cases it gives a stack overflow.

However, without the "hehe" the stack overflow occurs a bit sooner.

Lennox answered 1/3, 2010 at 11:4 Comment(1)
You're right Patrick, thanks! And thanks to litb for doubting the validity of my conculsion that recursion doesn't happen, which made me run it via gdb and now I'm satisfied to see a SIGSEGV which proves that in both cases a recursion occurs :)Obbard

© 2022 - 2024 — McMap. All rights reserved.