10

我想在实例之间有效地复制数据。std::streambuf也就是说,我想在它们之间铲起数据块,而不是执行逐个字符的复制。例如,这不是我要找的:

stringbuf in{ios_base::in};
stringbuf out{ios_base::out};
copy(istreambuf_iterator<char>{in},
     istreambuf_iterator<char>{},
     ostreambuf_iterator<char>{out});

为此存在语法糖,并进行了更多的错误检查:

ostream os{&out};
os << &in;

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;
                }

底线是:这仍然是按字符复制。我希望标准库使用一种算法,该算法依赖于流缓冲区的块级成员函数,sputnsgetn不是按字符传输。标准库是否提供这样的算法,还是我必须自己推出?

4

1 回答 1

2

恐怕答案是:以标准库的当前设计是不可能的。原因是流缓冲区完全隐藏了它们管理的字符序列。这使得无法直接将字节从一个流缓冲区的 get 区域复制到另一个流缓冲区的 put 区域。

如果“输入”流缓冲区会暴露其内部缓冲区,那么“输出”流缓冲区可以只使用sputn(in.data(), in.size()). 或者更明显的是:如果输出缓冲区也暴露了它的内部缓冲区,那么可以使用 plainmemcpy在两者之间铲除字节。其他 I/O 库以这种方式运行:例如 Google 协议缓冲区的流实现。Boost IOStreams 具有在流之间复制的优化实现。在这两种情况下,有效的块级复制都是可能的,因为流缓冲区等效项提供了对其中间缓冲区的访问。

事实上,具有讽刺意味的是,流缓冲区甚至不需要缓冲区:当无缓冲运行时,每次读/写都直接进入底层设备。大概这是标准库不支持自省的原因之一。不幸的结果是输入和输出流缓冲区之间的有效复制是不可能的。块级复制需要一个中间缓冲区,复制算法的操作如下:

  1. 从输入流缓冲区读取sgetn到中间缓冲区。
  2. 通过 . 从中间缓冲区写入输出流缓冲区sputn
  3. 转到 1。直到输入耗尽或写入输出流缓冲区失败
于 2016-05-29T04:57:48.763 回答