【问题标题】:C++ Odd behaviour with ostringstreamostringstream 的 C++ 奇怪行为
【发布时间】:2013-10-28 22:51:33
【问题描述】:

标准中是否对以下行为有任何解释?

以下代码:

#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 并且两者的行为方式相同,我已经尝试过该示例。

感谢您的帮助!

【问题讨论】:

  • 奇怪,这段代码在我的机器上用 g++ 打印“1 2 3\n1 2\n”。
  • @jma127 我在像 P.An. 这样的 Debian 上使用 g++ 4.8.1 得到了同样奇怪的结果

标签: c++ stl ostringstream


【解决方案1】:
const char *p = os1.str().c_str();

这就是问题所在,在上面一行中。

os1.str() 通过复制内部字符串缓冲区返回一个临时字符串对象。而且您正在使用临时对象的.c_str(),该对象在完整表达式的末尾被销毁。结果是,当您使用std::cout 打印时,p 指向被破坏的对象。

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

试试这个:

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

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

【讨论】:

  • 非常感谢您的帮助!
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

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

    string s = os1.str();
    const char *p = s.c_str();
    
    cout << os2.str() << endl;
    cout << p << endl;
    

    【讨论】:

    • 看起来保持引用也可以,如果我按以下方式更改代码,它会正确显示: const std::string& s = os1.str(); const char *p = s.c_str();
    猜你喜欢
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 2019-04-10
    相关资源
    最近更新 更多