This is my code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class TestLog: public std::stringstream
{
public:
~TestLog()
{
cout << (str()) << endl; // Why does this print an address ?
}
};
int main()
{
TestLog() << "Hello World!"; //test 1 print an address
stringstream ss;
ss << "Hello World!";
cout << (ss.str()) << endl; //test 2 print a string
return 0;
}
And the output:
0x401b90
Hello World!
Compiler info :
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
In my opinion,
(a)the str() method of std::stringstream return a string.
(b)std::cout is an object of std::ostream.
So both of the two test will call the same operator funtion of ostream and print same "Hello world".
But test 1 print an address , test 2 print the correct "Hello world".
What wrong with me ? Thanks.
ss << "Hello World!";
is resolved to a call to the following overload (#2 on this page):This overload decays the string literal into a
char const *
, then prints it.To stir the mud, we can try the following snippet:
This one will also resolve to the overload above, and print
Hello World!
. That is becausetl
is an lvalue which can bind to the first parameter that is a non-const
lvalue reference.In your example,
TestLog()
is an rvalue -- this overload cannot match! Thus another overload is chosen instead (#7 here):This one is a member function overload, and has been inherited from
std::stringstream
. Even though you can't bind a non-const
reference to an rvalue, you can call non-const
member functions on an rvalue. So this overload is a valid match, and it is chosen -- printing the address of the literal as if it were any old pointer.C++11 brought a new overload to solve this issue, visible at #3 here:
T const &
matches the literal'schar const[N]
type perfectly, so it is ranked higher than thevoid const *
overload. The rvalue reference as first parameters binds to the temporary just fine.Named rvalue references are considered lvalues, so this function can then call
os << value;
again to trampoline back into the overload set for an lvalue stream. Thus, in C++11 and above, both lines printHello World!
.