【发布时间】:2012-05-20 19:07:54
【问题描述】:
istreambuf_iterator 和 istream_iterator 有什么区别?
一般来说,流和流缓冲区有什么区别?
我真的找不到任何明确的解释,所以决定在这里问。
【问题讨论】:
istreambuf_iterator 和 istream_iterator 有什么区别?
一般来说,流和流缓冲区有什么区别?
我真的找不到任何明确的解释,所以决定在这里问。
【问题讨论】:
IOstreams 使用 streambufs 作为输入/输出的源/目标。实际上,streambuf-family 完成了有关 IO 的所有工作,而 IOstream-family 仅用于格式化和 to-string / from-string 转换。
现在,istream_iterator 接受一个模板参数,该参数说明来自 streambuf 的未格式化字符串序列应格式化为什么格式,例如 istream_iterator<int> 会将所有传入文本(空格分隔)解释为 ints。
另一方面,istreambuf_iterator 只关心原始字符,并直接遍历它所传递的 istream 的关联流缓冲区。
通常,如果您只对原始字符感兴趣,请使用istreambuf_iterator。如果您对格式化输入感兴趣,请使用istream_iterator。
我所说的所有内容也适用于ostream_iterator 和ostreambuf_iterator。
【讨论】:
istreambuf_iterator?
这是一个非常保守的秘密:一个 iostream 本身,几乎与从/向您的计算机上的文件进行实际读取或写入无关。
iostream 基本上充当 streambuf 和语言环境之间的“媒人”:
iostream 存储有关应如何进行转换的一些状态(例如,转换的当前宽度和精度)。它使用这些来指导语言环境如何以及在何处进行转换(例如,将此数字转换为该缓冲区中宽度为 8 和精度为 5 的字符串)。
虽然您没有直接询问它,但反过来,语言环境实际上只是一个容器——但(相当奇怪)一个类型安全的异构容器。它包含的东西是facets。一个 facet 对象定义了整个语言环境的一个 facet。该标准定义了从读取和写入数字(num_get、num_put)到分类字符(ctype 方面)的所有方面。
默认情况下,流将使用“C”语言环境。这是非常基本的——数字只是转换为数字流,它识别为字母的唯一内容是 26 个小写和 26 个大写英文字母,依此类推。但是,您可以 imbue 使用您选择的不同区域设置的流。您可以通过字符串中指定的名称选择要使用的语言环境。一个特别有趣的是由一个空字符串选择的。使用空字符串基本上告诉运行时库选择它“认为”最合适的语言环境,通常基于用户如何配置操作系统。这允许代码以本地化格式处理数据,而无需为任何特定语言环境明确编写。
因此,istream_iterator 和 istreambuf_iterator 之间的基本区别在于,来自 istreambuf_iterator 的数据没有经过(大部分)由语言环境完成的转换,而是来自 @ 987654332@ 已被语言环境转换。
对于它的价值,上一段中的“大部分”是指当您从 istreambuf(通过迭代器或其他方式)读取数据时,一点点基于语言环境的转换 完成:除了各种“格式化”类型的东西外,语言环境还包含一个 codecvt facet,它用于将某些外部表示转换为某些内部表示(例如,UTF-8 到 UTF-32)。
忽略它们都存储在语言环境中这一事实可能更有意义,而只考虑所涉及的各个方面:
这就是istream_iterator 和istreambuf_iterator 之间的真正区别。 (至少可能)对来自其中任何一个的数据进行了一点转换,但对来自istreambuf_iterator 的数据进行了大幅较少。
【讨论】:
codecvt转换一个字符,因为你从原始缓冲区中读取数据,我相信这通常会失去公平速度量(与一次转换整个缓冲区相比)。
std::endl,而你只需要\n)iostreams 在速度方面与C I/O 相当有竞争力。 stackoverflow.com/a/1926432/179910