我应该使用另一个流创建临时 ostream 吗?

Should I create a temporary ostream using another's streambuf?

本文关键字:ostream 创建 另一个 我应该      更新时间:2023-10-16

假设我有一个函数,它接受ostream &参数o并写入该ostream。operator <<实现就是一个很好的例子。

ostream& operator << (ostream& o, const MyThing& t)
{
  // ... interesting code here ...
  return o;
}

在函数中,我可能希望指定流的格式选项。例如,我可能希望一个数字打印为十六进制,无论o在传递给函数时是如何配置的。

其次,我可能希望能够对当前的格式化标志进行假设。例如,除非我另有要求,否则假设数字的格式为十进制会很好。

最后,当函数退出时,我希望o上的格式选项与调用函数之前相同,以便对调用方显示为不变。这只是对来电者的礼貌问题。

到目前为止,我已经通过在函数中创建一个本地ostringstream,完成我的所有工作(包括设置格式选项),并在函数结束时将.str()发送到o来实现这一点这里的StackOverflow问题表明,比我聪明的人也会采取同样的方法然而,我在ostringstream中保留了太多数据,这些数据可能会更早地发送到输出(字符串可能会变得很大),这让我很困扰。

我有两个问题:

1) 它合法、地道、形式好吗在o.rdbuf()周围创建一个临时(基于堆栈的)ostream,并在该ostream上进行我的工作?我自己的测试和cppreference.com上的页面似乎表明我可以。

ostream& operator << (ostream& o_, const MyThing& t)
{
  ostream o (o_.rdbuf());
  // write stuff to "o",
  // setting formatting options as I go.
  return o_; // Formatting on the parameter ostream o_ unchanged.
}

2) 还有其他我没有考虑过的更好的方法吗?

Boost IO状态保护程序正是为此目的而构建的。

这是一个不错的解决方案;这当然是合法的。我不认为这太常见了,所以评论一下可能是个好主意你为什么这么做。

我在这里看到的最常见的解决方案是创建一个状态saver类,它将保存您需要的所有状态(通常为flags()precision()fill())构造函数,并将其还原到析构函数中,然后强制设置所需的所有选项。(可能使用copyfmt进行此操作,尽管这也会复制以下内容例外面具,你可能不想玩它。)

设置可以存储在一种称为fmtflags对象的对象中,该对象在iostream中包含的名为ios的类中定义。您可以申报这些对象,但是您必须使用范围解析操作符来声明它。

以下语句将在变量old_settings中保存格式状态的某些方面:

ios::fmtflags old_settings = cout.flags();

然后,在使用新设置进行输出后,可以通过使用旧设置作为参数调用相同的函数来恢复旧设置:

cout.flags(old_settings);

其他设置可以通过成员功能获得和恢复。例如,

int old_precision = cout.precision();

将保存当前的精度规格。然后

cout.precision(old_precision);

将精度恢复到原始值