My question can be boiled down to, where does the string returned from stringstream.str().c_str() live in memory, and why can’t it be assigned to a const char*?
This code example will explain it better than I can
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream ss("this is a string\n");
string str(ss.str());
const char* cstr1 = str.c_str();
const char* cstr2 = ss.str().c_str();
cout << cstr1 // Prints correctly
<< cstr2; // ERROR, prints out garbage
system("PAUSE");
return 0;
}
The assumption that stringstream.str().c_str() could be assigned to a const char* led to a bug that took me a while to track down.
For bonus points, can anyone explain why replacing the cout statement with
cout << cstr // Prints correctly
<< ss.str().c_str() // Prints correctly
<< cstr2; // Prints correctly (???)
prints the strings correctly?
I’m compiling in Visual Studio 2008.
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. That’s why your code prints garbage.You could copy that temporary string object to some other string object and take the C string from that one:
Note that I made the temporary string
const, because any changes to it might cause it to re-allocate and thus rendercstrinvalid. It is therefor safer to not to store the result of the call tostr()at all and usecstronly until the end of the full expression:Of course, the latter might not be easy and copying might be too expensive. What you can do instead is to bind the temporary to a
constreference. This will extend its lifetime to the lifetime of the reference:IMO that’s the best solution. Unfortunately it’s not very well known.