我正在尝试更多地了解 I/O 流在 C++ 中如何工作,但我真的很困惑何时使用什么。
streambuf
到底是什么?streambuf
、string
或 istream
相比,我什么时候使用 vector
? (我已经知道最后三个,但不知道 streambuf
与它们相比如何,如果有的话。)
在
streambuf
的帮助下,我们可以在更低的水平工作。它允许访问底层缓冲区。
这里有一些很好的例子:使用 C++ Streambufs 进行复制、加载、重定向和发球并参考比较,这可能会有所帮助,
有关更多详细信息,请参阅:IOstream 库
流缓冲区代表输入或输出设备,并为该设备的未格式化 I/O 提供低级接口。另一方面,流通过基本的未格式化 I/O 函数,特别是通过格式化 I/O 函数(即
operator<<
和 operator>>
重载),为缓冲区提供了更高级别的包装器。流对象还可以管理流缓冲区的生命周期。
例如文件流有一个内部文件流缓冲区。流管理缓冲区的生命周期,缓冲区为文件提供实际的读写功能。流的格式化运算符最终访问流缓冲区的未格式化 I/O 函数,因此您只需使用流的 I/O 函数,而不需要直接接触缓冲区的 I/O 函数。
了解差异的另一种方法是查看它们对 locale 对象的不同用途。流使用与格式相关的方面,例如
numpunct
和 num_get
。您还可以预期自定义时间或金钱数据类型的流 operator<<
和 operator>>
的重载将使用时间和金钱格式化方面。然而,流缓冲区使用 codecvt 方面来在其接口使用的单位和字节之间进行转换。因此,例如,basic_streambuf<char16_t>
的接口使用char16_t
,因此basic_streambuf<char16_t>
内部默认使用codecvt<char16_t, char, mbstate_t>
将写入缓冲区的格式化char16_t
单位转换为写入底层设备的char
单位。因此,您可以看到流主要用于格式化,而流缓冲区为未格式化的输入或输出到可能使用不同外部编码的设备提供了低级接口。
当您只想对 I/O 设备进行未格式化的访问时,可以使用流缓冲区。如果您想设置共享一个流缓冲区的多个流,您也可以使用流缓冲区(尽管您必须仔细管理缓冲区的生命周期)。您可能还想使用一些特殊用途的流缓冲区,例如 C++11 中的
wbuffer_convert
,它充当 basic_streambuf<char>
的外观,使其看起来像宽字符流缓冲区。它使用构建时使用的 codecvt 方面,而不是使用附加到任何语言环境的 codecvt 方面。您通常可以通过简单地使用具有适当方面的语言环境的宽流缓冲区来实现相同的效果。