Why does outputting a string in an unnamed std :: ofstream give me a hex number?
I was trying to add some debug output to a C ++ 03 project and got some weird result. Here's a simplified test code:
#include <fstream>
int main()
{
{
std::ofstream file("/tmp/test.txt");
file << "hello" << " ... OK, this works\n";
}
std::ofstream("/tmp/test.txt",std::ios_base::app) << "hello"
<< " ... no, I mean hello!\n";
}
For some reason, this is what I get after compiling:
$ g++ test.cpp -o test && ./test && cat /tmp/test.txt
hello ... OK, this works
0x80487fe ... no, I mean hello!
Why am I getting a hexadecimal number when outputting a string to an unnamed std::ofstream
object? And why does the subsequent output of the second line work?
source to share
The usual operator<<
one we use to pass 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 );
An unnamed std::ofstream
object is a temporary variable, and temporary entries cannot bind to a nonconst reference, so this operator overload is not involved in overload resolution. The closest match is performed instead, the member function
std::basic_ostream& std::basic_ostream::operator<<(const void*);
which takes a pointer to erase and just prints its value. Since member functions can be called with a temporary object, this works. This explains the hexadecimal number in the output. Now, this statement returns the link std::basic_ostream&
. Since it is no longer a temporary object and is instead a reference to some nonconst object, you can successfully call a normal free function overload operator<<
that takes const char*
. This is why the second line is printed as expected.
Note that as of C ++ 11, the code will work as expected since we have an additional overload operator<<
that 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 a temporary binding to an rvalue reference.
To make your code work in C ++ 03, you can use a member function std::ostream::flush()
that returns a reference to a nonconst object and has no user-visible side effects on the object fstream
:
#include <fstream>
int main()
{
std::ofstream("/tmp/test.txt").flush() << "hello"
<< " ... OK, this now works too\n";
}
source to share