No references aren't only for streams. You could also write:
Code:
const complex& operator + (const complex& a, const complex& b)
Some would argue that it is better to do it with const references so you don't make a copy. When working with streams you pass a non-const reference because you want to modify the stream. For example, you want to output the data in your class. The only way to change an object passed into your function is if it is passed in by reference (as a reference or pointer). If you passed the stream in like you did the Complex object, then you'd get a copy of the stream and outputting wouldn't work.