参考: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; }
第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拷贝。