在c++中打印字符串到临时流对象
Printing a string to a temporary stream object in C++
我有一种特殊类型的ostringstream,我试图将文本输出为临时对象,但我遇到了一些麻烦。明确一点,这就是我想要做的:
ostringstream() << "PARTY DOWN!" << endl;
现在,在你说:"但是扎克,那些代码完全没有价值!"对象在行尾被销毁,你怎么知道它是否做了什么?",听我说完。我没有尝试使用普通的ostringstreams,而是使用派生类,其中析构函数实际上提供了数据退出对象的路径。实际上,它看起来更像这样:
specialstringstream() << "PARTY DOWN!" << endl;
其中specialstringstream有一个析构函数,它将文本转储到其他地方。
我不会详细说明我为什么这样做。你必须相信我,它对我需要做的事情是有意义的,它很好地适应了现有的、巨大的代码库。
问题来了:当我这样做的时候,一切都编译并运行了,但是我得到一个指针地址打印到我的输出,而不是"PARTY DOWN!"字符串。我确定发生这种情况是因为编译器选择执行流输出的操作符是ostream& operator<< (const void* val)
,而不是ostream& operator<< (ostream& out, const char* s )
。
我有一个模糊的想法,为什么,但我在如何解决它的损失。我能做些什么来让char*s打印到字符串流的临时实例中?
下面是SpecialStringStream对象的一个简短版本,它展示了以下行为:class SpecialStringStream : public ostringstream
{
public:
SpecialStringStream(ostream* regularStream)
{
regularStream_ = regularStream;
}
~SpecialStringStream()
{
if (regularStream_ != NULL)
(*regularStream_) << str();
}
private:
ostream* regularStream_;
};
当我这样做:SpecialStringStream(someStreamPtr) << "PARTY DOWN!" << endl;
,我得到一个指针地址,如"00444D60"在我的输出,而不是消息。
编辑:由于我是一个新手,无法回答我自己的问题,所以感谢所有的回复,以下是我决定的。
我想出了下面的解决方案,它可以在Visual c++ 8和我需要的所有其他编译器下工作。我创建了一个模板操作符,它基本上剥离了const SpecialStringStream的constness,将其强制转换为ostream,并让ostream操作符做它们的事情。请随意在评论中把它撕成碎片,并警告我我介绍的所有可怕的潜在bug !
template <class T>
std::ostream& operator<<(const SpecialStringStream &o, T msg)
{
return static_cast<std::ostream&>(const_cast<SpecialStringStream&>(o)) << msg;
}
重载ostream& operator<< (ostream& out, const char*)
是不可行的,因为您的临时对象不会绑定到非常量引用ostream&
。除了声明一个局部变量并使用它之外(因为你不能将一个右值转换为一个左值),你真的没有什么可以做的:
{
specialstringstream ss;
ss << "Hello world" << std::endl; // OK, can bind to lvalue
}
可能的解决方案:您可以声明另一个接受右值引用的重载:
std::ostream & operator<<(specialstringstream && o, const char * s)
{
return o << s; // note: *not* "std::move(o)"
}
你不想实现stringstream。您需要实现一个basic_streambuf,它写入到您的特殊字符串中。
流本身负责格式化和类似的功能;流bufs负责最终成为数据的接收器。
毕竟,stringstream只是一个iostream,附加了一个basic_stringbuf。
也许有更好的办法,但我想到了另一个解决方案:
#include <iostream>
#include <sstream>
class LogClass
{
template <typename T>
friend const LogClass& operator << (const LogClass& lc, const T& v);
public:
LogClass()
: str(new std::ostringstream())
, refCount(new int(1))
{}
LogClass(const LogClass& other)
: str(other.str)
{
++(*refCount);
}
~LogClass()
{
--(*refCount);
if (!*refCount)
{
delete refCount;
std::cout << str->str() << std::endl;
delete str;
}
}
private:
mutable std::ostringstream *str;
int *refCount;
LogClass& operator = (const LogClass&);
};
template <typename T>
const LogClass& operator << (const LogClass& lc, const T& v)
{
(*lc.str) << v;
return lc;
}
int main(int , char**)
{
for (size_t i = 0; i < 10 ; ++i)
{
LogClass() << "PARTY DOWN! " << i;
}
}
使用valgrind:
运行valgrind——tool=memcheck——leak-check=full ./LogClass
==16197== Memcheck,内存错误检测器
==16197== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==16197==使用Valgrind-3.7.0。SVN和LibVEX;使用-h重新运行版权信息
==16197== Command: ./LogClass
= = 16197 = =
党失望!0
党失望!1
党失望!2
党失望!3
党失望!4
党失望!5
党失望!6
党失望!7
党失望!8
党失望!9
= = 16197 = =
==16197== HEAP:
==16197== in use at exit: 0 bytes in 0 blocks
==16197==总堆使用率:40 allos, 40 free, 7,350 bytes分配
= = 16197 = =
==16197==释放所有堆块——不可能出现泄漏
= = 16197 = =
==16197==对于检测到和抑制的错误计数,使用-v
重新运行:==16197== ERROR SUMMARY: 0 errors from 0 contexts (suppression: 15 from 8)
这是我想要的,但它是不是线程安全的。使用boost中的shared_ptr来实现。
这是我使用的一个变通方法:
#define STRM2STR(x) (dynamic_cast<std::ostringstream &>(std::ostringstream() << std::dec << x).str())
插入std::dec将导致调用ostream::operator<<(ios_base&(*pf)(ios_base&))返回可用的ostream &
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- C++ 创建包含链表和字符串的对象的链接列表时出错
- 有没有办法让编译器在我放置字符串而不是 nlohmann::json 对象时抛出错误?
- 如何从文件中读取两个字符串和数字数组,并将它们存储在对象向量中
- 如何从字符串向量构造对象并避免复制?
- 在对象数组中搜索字符串并返回相应值的函数
- POCO C++对象到 JSON 字符串序列化
- 重载加法运算符(使用函数向对象添加字符串)
- 用字符串初始化我的类的对象
- C++ - 确定 const char* 是指向字符串文本对象还是动态对象
- 对象数组打印空白字符串
- 如何检索由带通配符的字符串索引的对象
- 在 c++ 中使用字符串变量选择静态类结构,而不带对象
- 在C++中,我想通过使用来自变量(例如字符串)的typename信息,从模板中定义一个类对象
- 如何删除作为C++联合的成员变量的字符串对象
- 如何定义此"if block"中其他无效输入的值,以便在c ++中将字符串转换为对象?
- C++-将对象(如字符串)映射到表中成员函数的正确方法
- C++指向对象的指针堆数组中,如何将字符串传递给特定对象?有一些代码请看一下:
- 如何提取由特定模式分开的JSON对象字符串
- C++ 不接受对象字符串中的@符号吗?似乎是地址问题?