参考:http://stackoverflow.com/questions/1374468/c-stringstream-string-and-char-conversion-confusion
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main ()
{
stringstream ss;
ss << "Hello";
const char * p = ss.str().c_str();
cout << p << endl;
return 0;
}
虽然在测试的CentOS 6.3,64bit机器上运行,输出了期望的"Hello",但上面代码中,第10、11行的做法不正确。原因如下:
第10行的ss.str()会生成一个临时string类型变量,第10行结束时,这个临时变量就释放了,但const char *指针p仍然指向那个临时变量的buffer。我们不能假设临时的string类型变量已经被释放(析构)了的情况下,它的buffer内容仍然有效,这样的假设是危险的。这里我们看到程序运行没有crash,并且输出了期望的结果,只能说在程序运行的过程中,string类型变量虽(包括它的buffer)然被释放了,但是它的buffer并没有被清空,同时指针p(已经是“野指针”了)指向这段内存,于是正确访问到了那段没变清空的内存,于是“正确输出了期望的结果”。实属侥幸。事实上,参考的帖子中,作者就遇到了“打印出garbage”的情况。
根据参考的帖子,一种可行的做法如下:
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main ()
{
stringstream ss;
ss << "Hello";
string s = ss.str();
const char * p = s.c_str();
cout << p << endl;
return 0;
}
其中,第10行
先将ss.str()这个临时变量copy到局部变量s中(注意s不会像ss.str()一样在ss.str()行执行完之后就被释放了,而是在出了作用域,即出了main函数时才被释放)。然后
再从s获取const char*指针。这个指针指向的buffer在第12行输出时仍然是有效,不会出现“打印出garbage”的情况。
然而,这样做,会多做一步string拷贝的操作,为了避免这个拷贝,可以像下面这样做。
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main ()
{
stringstream ss;
ss << "Hello";
const string &s = ss.str();
const char * p = s.c_str();
cout << p << endl;
return 0;
}
第10行,没有做实际的copy,而是
申明了一个const string类型的引用,引用了ss.str()这个临时变量,这样就“延长了临时变量ss.str()的生命周期”,使得ss.str()生命结束时刻和s一样。于是,虽然第11行p指向的是临时变量ss.str()的buffer,但这段buffer在第12行仍然有效。当然,
同时也避免了一道不必要的string拷贝。