ostrstream将常量字符串解释为指针 [英] ostrstream interprets constant string as pointer

查看:101
本文介绍了ostrstream将常量字符串解释为指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在清理旧的C/C ++应用程序的调试宏时遇到了这个问题:我们有一个从ostrstream继承的Tracer类(我知道自C ++ 98起就不推荐使用,但是此应用程序是用1998!),我们这样使用:

I ran across this problem while cleaning up the debug macros of an old C/C++ application: We have a Tracer class inheriting from ostrstream (I know it's been deprecated since C++98, but this application was written in 1998!) which we use like this:

Tracer() << "some" << " message" << " here";

现在,如果链中的第一个值是如上所述的常量字符串,则在Tracer上调用ostrstream::str()的结果(在析构函数中完成,将结果插入队列中)将包含指针的十六进制表示形式到此字符串而不是文本.因此,上面的语句将产生类似"0x401a37 message here"的内容.对于旧的宏,这不会发生,因为它们的第一个值总是很长(线程ID),现在已被删除.

Now if the first value in the chain is a constant string like above, the result of calling ostrstream::str() on the Tracer (which is done in the destructor, inserting the result into a queue) contains a hexadecimal representation of the pointer to this string instead of the text. Thus the above statement would yield something like "0x401a37 message here". This didn't occur with the old macros as they always had a long (Thread ID) as the first value which has now been removed.

使用gdb进入该目录显示,对于第一次插入,此操作在ostrstream上调用operator<<(void const*),而随后的插入调用operator<< <...>(basic_ostream<...>&, char const*)(出于可读性考虑将其删除).

Stepping into it with gdb showed that for the first insertion, this calls operator<<(void const*) on the ostrstream, while the subsequent insertions call operator<< <...>(basic_ostream<...>&, char const*) (templating removed for readability).

有人可以解释这种行为吗?有什么干净的方法可以解决此问题?我发现了一个简单的解决方法,它使用<< left作为第一个参数-这样安全吗?有更好的方法可以做到这一点吗?

Can somebody explain this behaviour? What would be a clean way to fix this? I have found an easy workaround, which is using << left as the first argument - is this safe? Are there better ways to do this?

这是一个最小化的示例:

Here's a minimized example:

#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";
}

推荐答案

之所以如此工作,是因为Tracer()是一个临时(右值),无法绑定到operator<<(basic_ostream<...>&,中的非常量引用.

It works this way because the Tracer() is a temporary (rvalue) that can not bind to the non-const reference in operator<<(basic_ostream<...>&, .

但是,您可以调用像operator<<(void const*)这样的成员函数,因为它不需要左值.

However, you can call member functions like operator<<(void const*), because that doesn't require an lvalue.

然后,成员函数返回对流对象的引用,可以在调用序列中的下一个operator<<时使用 .

The member function then returns a reference to the stream object which can be used in calling the next operator<< in the sequence.

以这种方式调用任何成员函数,例如Tracer() << leftTracer() << flush,因此将引用转换"为左值引用是非常安全的.

Calling any member function this way, like Tracer() << left or Tracer() << flush, and thus "convert" the reference to an lvalue reference is quite safe.

如果碰巧具有C ++ 11兼容的编译器,则标准库甚至包含一个operator<<(basic_ostream<...>&&,可以为您完成此操作.在那种情况下,您不再需要解决方法.

If you happen to have a C++11 compliant compiler, the standard library even contains an operator<<(basic_ostream<...>&&, which does this for you. In that case you don't need the workaround anymore.

这篇关于ostrstream将常量字符串解释为指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆