2

Rather than outputting the expected string of "Bar", the following code outputs what looks to be a pointer.

#include <sstream>
#include <iostream>

int main()
{
    std::stringstream Foo("Bar");
    std::cout << Foo << std::endl; // Outputs "0x22fe80."
    return 0;
}

This can be worked around by using Foo.str(), but it's caused some issues for me in the past. What causes this strange behavior? Where is it documented?

Maxpm
  • 24,113
  • 33
  • 111
  • 170
  • 1
    Since this was already answered I might as well put here what the address means, in case you're curious. Typically, to allow streams to be tested in boolean contexts operator void* is overloaded, this results (in some implementations) in code like `operator void *() const {return (fail() ? 0 : (void *)this);} ` which (if no fail flag is set) will return the address of the object itself. In some implementations this means the address of either a member of the class or the virtual table pointer, at least in vc++ it seems to do the latter. – lccarrasco Jun 19 '11 at 00:49

3 Answers3

6

This can be worked around by using Foo.str(), but it's caused some issues for me in the past. What causes this strange behavior? Where is it documented?

It's not strange at all.

A stream is a stream, not a string.

You can obtain the [string] buffer with the member function .str(). That's not a workaround: it's the API. It should be documented in your C++ standard library reference, and if it's not then your reference is incomplete/wrong.

(What is slightly strange is that you get a memory address rather than a compilation error; that is due to the use of the safe bool idiom in the pre-C++0x standard library, as covered in another answer.)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

A std::stringstream is not supposed to be inserted in a stream. That's why you have the str() method.

The behavior you're observing is due to the fact that std::stringstream has a conversion to void*, which is what is used to test the stream:

if(Foo) { // this uses the conversion to void*
}

In C++11, this conversion is replaced by an explicit conversion to bool, which causes this code not to compile:

std::cout << Foo << std::endl;
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • Why wouldn't it compile? Wouldn't it just output `1` or something? – Maxpm Jun 18 '11 at 23:33
  • 2
    No, because the conversion is explicit, meaning you'd have to write `std::cout << bool(Foo);`. Check this other answer for more info: http://stackoverflow.com/questions/6242296/conversion-function-for-error-checking-considered-good/6242355#6242355 – R. Martinho Fernandes Jun 18 '11 at 23:36
0

(1)use std::cout << Foo << std::endl; you should make sure stringstream has already overload "<<".

(2)if there is not overload "<<" , use std::cout << Foo << std::endl; may output the Foo's address.

Jerry Zhang
  • 1,198
  • 1
  • 17
  • 36