我在清理旧 C/C++ 应用程序的调试宏时遇到了这个问题:我们有一个 Tracer 类继承自ostrstream
(我知道它自 C++98 以来已被弃用,但此应用程序是 1998 年编写的!)我们使用像这样:
Tracer() << "some" << " message" << " here";
现在,如果链中的第一个值是上面的常量字符串,则调用ostrstream::str()
Tracer 的结果(在析构函数中完成,将结果插入队列)包含指向该字符串的指针的十六进制表示,而不是文本。因此,上面的语句会产生类似"0x401a37 message here"
. 旧的宏不会发生这种情况,因为它们总是将长(线程 ID)作为第一个值,现在已被删除。
使用 gdb 进入它表明,对于第一次插入,这调用operator<<(void const*)
了 ostrstream,而随后的插入调用operator<< <...>(basic_ostream<...>&, char const*)
(为了便于阅读而删除了模板)。
有人可以解释这种行为吗?什么是解决这个问题的干净方法?我找到了一个简单的解决方法,它<< left
用作第一个参数 - 这安全吗?有没有更好的方法来做到这一点?
这是一个最小化的示例:
#include <strstream>
#include <iostream>
using namespace std;
class Trace : public ostrstream {
public:
Trace();
virtual ~Trace();
};
Trace::Trace() : ostrstream() {}
Trace::~Trace() {
static_cast< ostrstream& >(*this) <<ends;
char * text = ostrstream::str();
cout << "MESSAGE: "<< text <<endl;
delete[] text;
}
int main(){
Trace() << "some" << " text" << " here";
Trace() << left << "some" << " text" << " here";
Trace() << 123 << " text" << " here";
}