C ++使用ostringstream的奇怪行为

时间:2013-10-20 13:07:35

标签: c++ stl ostringstream

标准中是否有以下行为的解释?

以下代码:

#include <sstream>
#include <iostream>

using namespace std;

int main()
{
    ostringstream os1;
    ostringstream os2;

    os1 << 1 << " " << 2;
    os2 << 1 << " " << 2 << " " << 3;

    const char *p = os1.str().c_str();

    cout << os2.str() << endl;
    cout << p << endl;

    return 0;
}

显示输出:

1 2 3
1 2 3

但是,我希望它能显示出来:

1 2 3
1 2 

看起来os1对象在某种程度上受到os2的影响,如果我删除os2.str()调用,示例行为正确。

如果Solaris Studio 12.2和G ++ 4.8.1都以相同的方式运行,我尝试过该示例。

感谢您的帮助!

3 个答案:

答案 0 :(得分:4)

const char *p = os1.str().c_str();

以上是问题所在。

os1.str()通过复制内部字符串缓冲区返回临时字符串对象。而你正在使用.c_str()临时对象,它会在完整表达式结束时被销毁。结果是,当您使用p进行打印时,std::cout指向被销毁的对象。

也就是说,您的程序调用未定义的行为(UB)。

试试这个:

auto s = os1.str();  
const char *p = s.c_str(); //s is not a temporary object anymore!

现在它提供correct output(这是your code - 幸运的是,即使coliru也提供了与您在计算机上观察到的相同的输出。请注意,此输出尽管保证正是因为代码调用了UB。)。

答案 1 :(得分:2)

我认为问题与保留c_str()返回的指针有关。

ostringstream::str()正在返回一个临时字符串对象,并且您正在保存指向其内部char数组的指针。但是一旦该行执行,返回的字符串对象将被删除。所以你的指针无效。

如果由于某种原因想要保留c_str指针,则还需要保留字符串的副本:

string s = os1.str();
const char *p = s.c_str();

cout << os2.str() << endl;
cout << p << endl;

答案 2 :(得分:0)

这个问题的答案在这里: stringstream, string, and char* conversion confusion

stringstream.str()返回一个临时字符串对象,该对象在完整表达式的末尾被销毁。如果你从那里得到一个指向C字符串的指针(stringstream.str()。c_str()),它将指向一个字符串,该字符串在语句结束时被删除。