注意stringstream.str()临时变量的lifecycle

参考: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拷贝


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值