I know that indexing operator implementations usually return references so that the values can be set as well as retrieved, but why do streams?
Streams do not support copying or assignment, so anything that passes or returns a stream must use either a pointer or reference. You can't use overloaded operators on a pointer (without dereferencing it) because they'd try to apply the built-in operator to the pointer itself.
So, returning a reference is the only choice that supports operator chaining.
So you can chain them together.
cout << "hello" << "how are you";
Works because cout << "hello"
returns a reference to the cout so that << "how are you"
knows there to put itself.
Most operators, such as +=
, also do this.