c++ - stringstream临时ostream返回问题

标签 c++ iostream stringstream temporary

我正在创建一个包含以下部分的记录器:

// #define LOG(x) // for release mode
#define LOG(x) log(x)

log(const string& str);
log(const ostream& str);

有了想法去做:

LOG("Test");
LOG(string("Testing") + " 123");
stringstream s;
LOG(s << "Testing" << 1 << "two" << 3);

这一切都按预期工作,但当我这样做时:

LOG(stringstream() << "Testing" << 1 << "two" << 3);

它不起作用:

void log(const ostream& os)
{
  std::streambuf* buf = os.rdbuf();
  if( buf && typeid(*buf) == typeid(std::stringbuf) )
  {
    const std::string& format = dynamic_cast<std::stringbuf&>(*buf).str();
    cout << format << endl;
  }
}

导致“格式”包含垃圾数据而不是通常的正确字符串。

我认为这是因为 << 运算符返回的临时 ostream 比它来自的 stringstream 还长。

还是我错了?

(为什么 string() 以这种方式工作?是因为它返回对自身的引用吗?我假设是的。)

我真的很想这样做,因为我会在以 Release模式登录时消除额外的分配。

任何以这种方式完成它的指示或技巧都将受到欢迎。在我的实际解决方案中,我有许多不同的日志功能,而且它们都比这更复杂。所以我更愿意在调用代码中以某种方式实现它。 (如果可能的话,不要修改我的#define)

只是给出一个想法,我的一个实际#defines 的例子:

#define LOG_DEBUG_MSG(format, ...) \
  LogMessage(DEBUG_TYPE, const char* filepos, sizeof( __QUOTE__( @__VA_ARGS__ )), \
  format, __VA_ARGS__)

它匹配采用 char*、string() 和 ostream() 的可变参数 printf 类日志函数以及采用 string()、exception() 和 HRESULT 的非可变参数函数。

最佳答案

认为我明白发生了什么。这会产生预期的输出:

log(std::stringstream() << 1 << "hello");

虽然这不是:

log(std::stringstream() << "hello" << 1);

(它写入一个十六进制数,后跟数字“1”)

解释的几个要素:

  • 右值不能绑定(bind)到非常量引用
  • 在临时对象上调用成员函数是可以的
  • std::ostream 有一个成员运算符<<(void*)
  • std::ostream 有一个成员运算符<<(int)
  • 对于 char* 运算符不是成员,它是 operator<<(std::ostream&, const char*)

在上面的代码中,std::stringstream() 创建了一个临时的(右值)。它的生命周期没有问题,因为它必须持续声明它的整个完整表达式(即,直到对 log() 的调用返回)。

在第一个示例中,一切正常,因为首先调用了成员 operator<<(int),然后可以将返回的引用传递给 operator<<(ostream&, const char*)

在第二个例子中,operator<<(不能用“std::stringstream()”作为第一个参数调用,因为这需要它绑定(bind)到非常量引用。但是,成员 operator<<(void*) 可以,因为它是成员。

顺便说一句:为什么不将 log() 函数定义为:

void log(const std::ostream& os)
{
    std::cout << os.rdbuf() << std::endl;
}

关于c++ - stringstream临时ostream返回问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1540831/

相关文章:

c++ - 如何给现有项目添加CUDA 7.0加速?

c++ - 覆盖代码体中的虚函数

C++ getline() 与 boost::iostreams::filtering_istream 工作起来很奇怪

c++ - fstream、ofstream、ostream、iostream 之间的区别

c++ - 计划意外结束

c++ - 提升 : read_until "\n" reads until ""

C++:如何构建两个空格分隔字符串的交集字符串?

c++ - bitset<4> 在 Win7 Embedded 上转换为错误值

c++ - std::stringstream 是否有两个缓冲区,因此有两个标记?

c++ - 如何在 C++ 中对 string[] 进行排序