【问题标题】:Is there any standard solution for buffering output operations in C++?在 C++ 中缓冲输出操作是否有任何标准解决方案?
【发布时间】:2011-02-17 14:42:23
【问题描述】:

我写了这个简单的类,它为一般的输出操作提供缓冲:

template <typename T>
class WriteBuffer {
        typedef void (&flush_t)(const T* values, const size_t size);

    public:
        WriteBuffer(size_t size, flush_t flush) : flush_(flush) {
            v_.reserve(size);
        }

       ~WriteBuffer() { flush(); }

        void flush() {
            if (v_.size() > 0) {
                flush_(&v_[0], v_.size());
                v_.clear();
            }
        }

        void write(const T value) {
            if (v_.size() == v_.capacity())
                flush();
            v_.push_back(value);
        }

    private:
        vector<T> v_;
        flush_t flush_;
};

(为简单起见,省略了错误检查。)以下示例程序:

void writeInt(const int* values, const size_t size) {
    cout << "Writing buffer of size " << size << ": " << endl;
    for (size_t i = 0; i < size; ++i)
        cout << values[i] << ", ";
    cout << endl;
}

int main(int argc, char* argv[]) {
    WriteBuffer<int> buffer(5, writeInt);

    for (size_t i = 0; i < 18; ++i)
        buffer.write(i);

    return 0;
}

然后生成以下输出:

大小为 5 的写入缓冲区:0, 1, 2, 3, 4, 大小为 5 的写入缓冲区:5、6、7、8、9、 大小为 5 的写入缓冲区:10、11、12、13、14、 大小为 3 的写入缓冲区:15、16、17、

这个问题是否有任何标准/更好的解决方案,例如一些具有类似功能的 STL 容器/BOOST 类?谢谢!

附加问题:您更喜欢使用函数对象而不是函数引用flush_t

编辑

我想为任何类型的T 和客户端提供的任何flush 操作使用这种缓冲(不仅是字符和输出流)。例如:

template <typename T>
void write(const T* values, const size_t size) {
    ...
    H5Dwrite(..., values);
    ...
}

WriteBuffer<unsigned long> buffer(8192, write<unsigned long>);

将数据写入 HDF5 数据集。 (此处不解决 HDF5 数据类型。)

【问题讨论】:

  • 您是否正在考虑选择内存数据库?
  • @DumbCoder:抱歉,我对 IMDB 几乎一无所知。我只需要将大量(按顺序生成的)数据写入 HDF5 文件,并且不想每次都调用H5Dwrite()(测量缓冲写入性能不佳)。

标签: c++ buffering


【解决方案1】:

标准解决方案是子类化 std::streambuf,这正是为您的任务而设计的。有一些boost magic 来简化实现。

【讨论】:

  • 感谢您的提示。至于std::streambuf,引用:流的基本缓冲区类; streambuf 对象负责为某些类型的字符序列(例如外部文件或字符串)提供读写功能。 但我正在寻找适用于任何类型(不仅仅是字符)的通用解决方案,并且客户端提供的任何输出(不仅仅是流)。 std::streambuf可以这样做吗?
  • @Daniel: std::streambuf 不知道实际存储的对象,它只是一个用于裸内存缓冲的接口(它使用char)。它是标准 iostream 的底层缓冲机制,正如您可能知道的,它以实际字符类型为模板。很容易想象使用streambuf 对象来存储任何对象类型。您可能希望在将对象放入streambuf 之前对其进行序列化,因为它根本不处理对象管理。这取决于您打算将缓冲区类用于什么。
  • @Daniel:由于您使用的是 HDF5,它会满足您的需求,因为序列化数字数据(几乎)是微不足道的。
【解决方案2】:

cout 默认是缓冲输出。您对 endl 的使用会强制缓冲区刷新其输出,但您可以使用 "\n" intead。如果您的程序需要使用标志 unitbuf 或操纵器 flush 或 endl 并且您希望避免刷新缓冲区,则可以使用不使用 sync() 的特殊流缓冲区来刷新流缓冲区,但我从来没有需要,所以我不清楚实现细节。

【讨论】:

  • 感谢您的回答,但我不想将其用于标准输出或流,这只是一个示例。请在关于 HDF5 的问题下方查看我的评论。
猜你喜欢
  • 2011-02-24
  • 2013-11-28
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 2012-06-09
  • 1970-01-01
相关资源
最近更新 更多