mav*_*vam 10 c++ iostream streambuf
我想在实例之间有效地复制数据std::streambuf.也就是说,我想在它们之间铲除数据块,而不是执行逐字符复制.例如,这不是我想要的:
stringbuf in{ios_base::in};
stringbuf out{ios_base::out};
copy(istreambuf_iterator<char>{in},
istreambuf_iterator<char>{},
ostreambuf_iterator<char>{out});
Run Code Online (Sandbox Code Playgroud)
这有一个语法糖,有更多的错误检查:
ostream os{&out};
os << ∈
Run Code Online (Sandbox Code Playgroud)
这是operator<<(basic_streambuf<..>*)我标准库(Mac OS X,XCode 7)中实现的片段:
typedef istreambuf_iterator<_CharT, _Traits> _Ip;
typedef ostreambuf_iterator<_CharT, _Traits> _Op;
_Ip __i(__sb);
_Ip __eof;
_Op __o(*this);
size_t __c = 0;
for (; __i != __eof; ++__i, ++__o, ++__c)
{
*__o = *__i;
if (__o.failed())
break;
}
Run Code Online (Sandbox Code Playgroud)
底线是:这仍然是每个字符的复制.我希望标准库使用的算法依赖于streambuffers的块级成员函数,sputn而sgetn不是每个字符的传输.标准库是否提供了这样的算法,还是我必须自己编写?
恐怕答案是:以标准库当前的设计是不可能的。原因是流缓冲区完全隐藏了它们管理的字符序列。这使得无法直接将字节从一个流缓冲区的获取区域复制到另一个流缓冲区的放置区域。
如果“输入”流缓冲区将公开其内部缓冲区,则“输出”流缓冲区可以只使用sputn(in.data(), in.size()). 或者更明显的是:如果输出缓冲区也暴露了其内部缓冲区,那么就可以使用 plainmemcpy在两者之间铲除字节。其他 I/O 库也以这种方式运行:例如 Google 的 Protocol Buffers 的流实现。Boost IOStreams 有一个优化的实现来在流之间进行复制。在这两种情况下,高效的块级复制都是可能的,因为流缓冲区等效项提供了对其中间缓冲区的访问。
事实上,具有讽刺意味的是,流缓冲区甚至不需要缓冲区:当无缓冲操作时,每个读/写都直接进入底层设备。想必这就是标准库不支持内省的原因之一。不幸的结果是输入和输出流缓冲区之间不可能进行有效的复制。块级复制需要中间缓冲区,复制算法的操作如下:
sgetn到中间缓冲区。sputn。