The usual operator<<
which we use for passing C strings to std::ostream
is declared as a free function
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
The unnamed std::ofstream
object is a temporary variable, and temporaries can't bind to a nonconst reference, thus this operator overload doesn't participate in overload resolution. Instead, the closest match is taken, a member function
std::basic_ostream& std::basic_ostream::operator<<(const void*);
, which takes a type-erased pointer and just prints its value. Since member functions can be called with the object being a temporary, this one does work out. This explains the hex number in output. Now, this operator returns a reference, std::basic_ostream&
. As this is no longer a temporary object and is instead a reference to some nonconst object, the usual free-function overload of operator<<
, which takes const char*
, can be successfully called. This is why the second string is printed as expected.
Note that since C++11 the code will work as expected, since there we have an additional overload of operator<<
, which takes an rvalue reference:
template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
const T& value );
, and the temporary does bind to rvalue reference.
To make the code work in C++03, you can use a member function std::ostream::flush()
, which returns a nonconst reference to the object and doesn't have any user-visible side effects on the fstream
object:
#include <fstream>
int main()
{
std::ofstream("/tmp/test.txt").flush() << "hello"
<< " ... OK, this now works too\n";
}