流的内容和返回的字符串“str()”之间的差异

Difference between content of stream and the string `str()` returns?

本文关键字:str 之间 返回 字符串      更新时间:2023-10-16

我使用的是一小段生成PDF文件的代码,我在互联网上找到了它,并试图(温和地)优化它,因为创建文件需要很长时间。在分析之后,我将其缩小为以下代码:

std::ostringstream tmp;
tmp << std::hex << std::uppercase << std::setfill('0') <<
    std::setw(2) << r << " " <<
    std::setw(2) << g << " " <<
    std::setw(2) << b;
out << tmp.str();

在一个紧密的循环中发现,out是一个ostringstream,它在写入文件之前基本上包含了整个PDF内容。我发现tmp.str()是该循环中花费最多时间的一行,并且在查找C++引用时发现str()将返回流的底层字符串的副本。

然后,我认为删除该副本并直接使用out会更快。所以我抛弃了tmp,直接做了:

out << std::hex << std::uppercase << std::setfill('0') <<
    std::setw(2) << r << " " <<
    std::setw(2) << g << " " <<
    std::setw(2) << b;

但现在,生成的PDF文件被认为是"损坏的",PDF阅读器无法打开,而上一个可能是。我用这两种方法创建了一个PDF(有tmp流和没有)来比较输出的行,但没有发现明显的差异。。。

那么,这可能是什么原因呢?有理由使用那个临时流吗?是吗?为什么它与直接使用out流不同?

我认为它可能与换行符或操纵器有关,但在这些上找不到任何重要的东西

需要考虑的是,io操纵器(例如std::hex)在流上从该点向前是持久的。

因此,一旦插入std::hex操纵器,所有积分值都将从此点开始以十六进制格式打印出来。

您以前的方法没有这个问题,因为操纵器在瞬态流上。完成后,您可以尝试插入std::dec操纵器。。。

根据Jan Hudec的评论,Boost IO State Savers是干净处理这一问题的好方法。

另一个小区别是:如果std::ostringstream的格式化输出失败,则目标输出不会受到影响。

(尼姆的回答描述了实际问题)