Ostrstream将常量字符串解释为指针
ostrstream interprets constant string as pointer
我在清理旧C/c++应用程序的调试宏时遇到了这个问题:我们有一个继承自ostrstream
的跟踪器类(我知道它自c++ 98以来已被弃用,但这个应用程序是在1998年编写的!)我们像这样使用它:
Tracer() << "some" << " message" << " here";
现在,如果链中的第一个值是一个常量字符串,那么在Tracer上调用ostrstream::str()
的结果(在析构函数中完成,将结果插入到队列中)包含指向该字符串的指针的十六进制表示形式,而不是文本。因此,上面的语句将产生类似"0x401a37 message here"
的东西。这在旧的宏中没有发生,因为它们总是将长(线程ID)作为第一个值,现在已被删除。
使用gdb进行深入研究表明,对于第一次插入,它调用了strstream上的operator<<(void const*)
,而随后的插入调用了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";
}
这样做是因为Tracer()
是一个临时的(右值),不能绑定到operator<<(basic_ostream<...>&,
中的非const引用。
但是,您可以调用operator<<(void const*)
这样的成员函数,因为它不需要左值。
成员函数然后返回一个对流对象的引用,可以用于调用序列中的下一个operator<<
。
以这种方式调用任何成员函数,如Tracer() << left
或Tracer() << flush
,从而将引用"转换"为左值引用是非常安全的。
如果你碰巧有一个c++ 11兼容的编译器,标准库甚至包含一个operator<<(basic_ostream<...>&&,
来为你做这些。在这种情况下,你就不需要变通了。
首先注意,以const char*
为参数的operator<<
是一个非成员函数。并且存在一个以void const*
为参数的成员函数
在你的代码中,表达式Trace() << "xyz"
只能调用成员函数,因为Trace()
创建了一个临时,它不能绑定到非成员operator<<
函数的第一个参数,因为这些函数的第一个参数是std::ostream&
,这是一个非const引用。所以Trace() << "xyz"
解析为成员 operator<<
,它以void*
为参数,输出地址!
我的建议:
- 不要继承流类(
std::ostrstream
是弃用)。 - 在流类上写一个简单的包装器,重载
operator<<
下面是一个例子:
#include <sstream> //for std::ostringstream
struct Trace
{
std::ostringstream ss;
template<typename T>
Trace& operator << (T const & data)
{
ss << data;
return *this;
}
~Trace()
{
std::cout << ss.str() << std::endl;
}
};
现在你可以这样使用:
Trace() << "Hello Worldn" << 100 << "nByen";
输出:Hello World
100
Bye
现场演示
- MSVC将仅移动结构参数解释为指针
- 我是c ++的新手,你能解释一下在这种情况下的指针吗
- 如果整数与指针大小相同,则重新解释将整数转换为指针双射是否具有双射作用?
- 指向 POD 类型的指针之间的静态转换与重新解释转换
- 您将如何使用标准引号解释指向基类和派生类成员的指针的这种差异?
- 返回指针的语句 - 解释它是如何工作的以及为什么
- 使C 将指针解释为零
- MPI_Op_create:候选功能不可行.自定义结构指针不能解释为空指针
- 如何判断 std::vector 是否调整了自身大小,以及如何解释指向向量内值的指针不再有效
- 通过指针访问数据(重新解释转换)与 .或 ->运算符
- 重新解释朱莉娅中的指针
- 请解释带指针的数组
- C++:带有cout和指向char的指针的无法解释的行为
- 解释如何正确初始化和删除指针向量
- 更好地解释C++指针功能
- 如何解释这种奇怪的输出?关于指针和临时变量
- 编译器未将指向字符串文本的良好指针解释为方法的参数
- 用指针解释复杂的类型定义
- 任何人都可以根据指针解释该程序的输出
- 将指针解释为二维数组