Question

Is there any explanation in the standard for the below behavior?

The following code:

#include <sstream>
#include <iostream>

using namespace std;

int main()
{
    ostringstream os1;
    ostringstream os2;

    os1 << 1 << " " << 2;
    os2 << 1 << " " << 2 << " " << 3;

    const char *p = os1.str().c_str();

    cout << os2.str() << endl;
    cout << p << endl;

    return 0;
}

displays the output:

1 2 3
1 2 3

However, I would expect it to display:

1 2 3
1 2 

It looks like os1 object is somehow influenced by os2, if I remove the os2.str() call, example behaves correctly.

I have tried the example if Solaris Studio 12.2 and G++ 4.8.1 and both behave in the same way.

Thanks for your help!

Was it helpful?

Solution

const char *p = os1.str().c_str();

Here is the problem, in the above line.

os1.str() returns a temporary string object by copying the internal string buffer. And you're taking .c_str() of the temporary object, which gets destroyed at the end of the full expression. The result is, p points to the destroyed object when you take it to print using std::cout.

That is, your program invokes undefined behavior (UB).

Try this:

auto s = os1.str();  
const char *p = s.c_str(); //s is not a temporary object anymore!

Now it gives correct output (and this is your code — luckily even coliru gives the same output as you observed on your machine. Note that this output is not guaranteed though precisely because the code invokes UB.).

OTHER TIPS

I think the issue has to do with retaining the pointer returned by c_str().

ostringstream::str() is returning a temporary string object, and you are saving a pointer to it's internal char array. But once that line has executed, the returned string object will be deleted. So your pointer will be invalid.

If you want to keep a c_str pointer around for some reason, you would need to also keep a copy of the string:

string s = os1.str();
const char *p = s.c_str();

cout << os2.str() << endl;
cout << p << endl;

The answer to this question is here: stringstream, string, and char* conversion confusion

stringstream.str() returns a temporary string object that's destroyed at the end of the full expression. If you get a pointer to a C string from that (stringstream.str().c_str()), it will point to a string which is deleted where the statement ends.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top