基于std :: vector <char> </char>创建std :: stringbuf

时间:2012-03-26 08:44:31

标签: c++ iostream

我在两个框架(OpenSceneGraph和wxWidgets)之间进行内存中图像转换。我不想关心底层类(osg::ImagewxImage),我使用了这两种API提供的面向流的I / O特性:

1)创建std::stringstream

2)使用OSG的作者写入流

3)使用wxWigdets阅读器从流中读取

这很有效。到目前为止,我一直在使用直接访问流缓冲区,但我最近注意到std::stringstream的“非连续底层缓冲区”问题。我一直在使用kludge来获取const char* ptr到缓冲区 - 但它有效(在Windows,Linux和OSX上测试,使用MSVC 9和GCC 4.x),所以我从来没有修复它。

现在我明白这段代码是定时炸弹,我想摆脱它。这个问题已经在SO(here for instance)上多次提出,但我找不到能够真正帮助我做最简单的事情的答案。

我认为最合理的做法是在幕后使用矢量创建自己的streambuf - 这可以保证缓冲区是连续的。我知道这不是一般的解决方案,但考虑到我的限制:

1)所需的大小无限且实际上是可预测的

2)因为API,我的流确实需要是std::iostream(我不能使用原始字符数组)

任何人都知道如何使用字符向量自定义stringbuf?请不要回答“使用std::stringstream::str()”,因为我知道我们可以,但我正在寻找别的东西(即使你说复制2-3 MB是这样的很快,我甚至都没有注意到差异,让我们考虑一下我仍然对定制的字符串组件感兴趣,只是为了练习的美感。)

2 个答案:

答案 0 :(得分:3)

如果您只能使用istreamostream(而不是 双向),不需要寻求,这很简单(约10 代码行)使用streambuf创建您自己的std::vector<char>。 但除非字符串非常非常大,为什么要费心呢? C ++ 11标准 保证std::string是连续的;那个char*&myString[0]获得的可以用作C风格的数组。而且 原因C ++ 11补充说这个保证是为了表彰现有的 实践;根本没有任何实现,这不是 case(现在它是必需的,将不会有任何实现) 未来的情况并非如此)。

答案 1 :(得分:1)

boost :: iostreams有一些现成的接收器。有array_sink如果你有某种上限并且可以预先分配块,那么这样的接收器不会动态增长,但另一方面也可能是积极的。还有back_inserter_device,它更通用,例如可以直接使用std::vector。使用back_inserter_device的示例:

#include <string>
#include <iostream>
#include "boost/iostreams/stream_buffer.hpp"
#include "boost/iostreams/device/back_inserter.hpp"
int main() 
{
    std::string destination;
    destination.reserve( 1024 ); 
    boost::iostreams::stream_buffer< boost::iostreams::back_insert_device< std::string > > outBuff( ( destination ) );
    std::streambuf* cur = std::cout.rdbuf( &outBuff );
    std::cout << "Hello!" << std::endl;
    // If we used array_sink we'd need to use tellp here to retrieve how much we've actually written, and don't forgot to flush if you don't end with an endl!
    std::cout.rdbuf( cur );
    std::cout << destination;
}