C++ 与涎溪流的奇怪行为

C++ Odd behaviour with ostringstream

本文关键字:C++      更新时间:2023-10-16

标准中对以下行为有什么解释吗?

以下代码:

#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 都以相同的方式运行。

感谢您的帮助!

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!

现在它给出了正确的输出(这是你的代码——幸运的是,即使是 coliru 也提供了与你在机器上观察到的相同的输出。请注意,不能保证此输出,但正是因为代码调用了 UB。

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

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

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

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

这个问题的答案在这里:字符串流、字符串和字符* 转换混淆

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

相关文章:
  • 没有找到相关文章