stringstream string char* convert 转换陷阱

stringstream string char* convert 转换陷阱

c++中字符流操作类stringstream可以说是非常的便利,然而正确使用也是非常重要的!!!
看如下Demo:

#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;
}

可以猜猜,输出结果,是不是你想要的结果…

好吧,注释已经把结果说出来了

再看一个

#include <string>
#include <sstream>
#include <iostream>

using namespace std;
int main()
{
    stringstream ss("012345678901234567890123456789012345678901234567890123456789");
    stringstream t_ss("qazxsw01245");
    string str1(ss.str());

    const char* cstr1 = str1.c_str();
    const char* cstr2 = ss.str().c_str();
    const char* cstr3 = ss.str().c_str();
    const char* cstr4 = ss.str().c_str();
    const char* t_cstr = t_ss.str().c_str();

    cout << "------ The results ----------" << endl
         << "cstr1:\t" << cstr1 << endl
         << "cstr2:\t" << cstr2 << endl
         << "cstr3:\t" << cstr3 << endl
         << "cstr4:\t" << cstr4 << endl
         << "t_cstr:\t" << t_ss.str().c_str() << endl
         << "-----------------------------" << endl;
    cin.get();
    return 0;
}

使用vs 2015编译输出结果如下:

------ The results ----------
cstr1:  012345678901234567890123456789012345678901234567890123456789
cstr2:  葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺
cstr3:  葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺
cstr4:  葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺
t_cstr: 
t_ss.str().c_str():     qazxsw01245
-----------------------------

到这里想必能猜出个为什么吧?stringstream.str()执行后得到一个临时string对象,表达式执行完毕后会销毁掉,内存里头内容全部失效,所以
const char* cstr4 = ss.str().c_str(); 执行完毕后临时对象销毁,cstr4所指向的内存内容实际上是失效的,即所谓的 garbage,当使用cstr4的时候就出现问题了

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.

解决办法

  1. 只使用一次,每次使用的重新转换一遍
cout << "t_cstr:\t" << t_ss.str().c_str() << endl;

这种方法简单,但是缺点很明显,每次使用都要重新生成一个临时对象,性能上有些开销

  1. 使用一个string接收临时对象,拷贝其内容,延长生命周期,多次使用
string str1(ss.str());
cout <<<< "cstr1:\t" << str1.c_str() << endl;
cout <<<< "cstr1:\t" << str1.c_str() << endl;
cout <<<< "cstr1:\t" << str1.c_str() << endl;

发表评论

电子邮件地址不会被公开。 必填项已用*标注