Reputation: 603
For function declaration like
ostream& operator<< (ostream& os, const unsigned char* s);
I am wondering what has been returned. The CPP reference says it returns ostream object. But why it is ostream& instead of simple ostream?
Thank you
Upvotes: 5
Views: 7047
Reputation: 10770
First reason: std::ostream
s are not copyable in general (in C++11 the copy constructor is actually delete
d). You don't want to return a copy anyway because chaining wouldn't work:
std::stringstream s;
s << "String1" << "String2";
would fail to compile because because the copy returned by the first operator call would not be convertible to the reference required for the second call.
Making both values instead of references also wouldn't work:
std::stringstream s;
s << "String1" << "String2";
assert(s.str() == "String1String2");
Your code will compile but the assert will fail because the object s
remains unmodified after these calls because it was passed by copy instead of by reference.
Second reason: all the actual stream
objects you will use derive from std::ostream
. If this parameter were passed by copy then you get slicing where you effectively lose the object you were using.
This means the following code wouldn't work (if passing by reference but returning by copy- and somehow getting around the compilation error?):
std::stringstream s;
s << "String1" << "String2" << std::endl;
assert(s == "String1String2");
s
would only hold "String1"
in this case because when you returned the std::stringstream
by copy of std::ostream
, the returned object is no longer a std::stringstream
object and calling operator<<
on that passes "String2"
into a temporary object which just gets destroyed by the end.
Those are the two important reasons I can think of to return by reference and not by value.
Upvotes: 4
Reputation: 5980
The reason that the operator returns a ostream&
(i.e. a modifiable reference to an ostream
object), rather than a copy or void is that it allows for chaining, for instance, a common example with std::cout
as the ostream
object:
unsigned int i = 2;
std::cout << "This is a test to print " << "some text and maybe some numbers: " << i << std::endl;
Here we chain two const char*
s, an unsigned int
and a stream modifer, without having to seperate them with separate lines, this makes it nicer to read and understand.
Upvotes: 5
Reputation: 417
Returning simple objects would require the compiler to generate an object copy but returning references don't.
Upvotes: 1
Reputation: 2179
Because you return "os" like that you can do a chaining;
std::cout << "string1" << "string2" << std::endl;
Upvotes: 1