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()),它将指向一个字符串,该字符串在语句结束的地方被删除。
相关文章:
- 没有找到相关文章