【问题标题】:How to fill a buffer generically and efficiently? (Pass insert iterators? Containers? etc.)如何一般有效地填充缓冲区? (通过插入迭代器?容器?等)
【发布时间】:2012-07-07 05:25:26
【问题描述】:

如果我正在创建一个需要填充缓冲区的方法(例如,fread 的包装器),并且在某些 情况下(在运行时确定)它可以做出很好的猜测在所需的缓冲区大小下,我应该将什么传递给此方法以利用这个机会,同时仍然允许任何合理类型的缓冲区并且不需要用户多次调用?

  • 喜欢使用insert_iterator,但我不能告诉它保留一定数量的内存。

  • 另一方面,如果我将 container 作为模板参数传递,我会遇到麻烦,因为容器没有标准接口! (例如vectorstringreserve,但dequelist 没有。或者容器可能没有push_back - 我不相信我已经看到这是强制性的。等等)

那么在这样的情况下应该怎么做呢?

【问题讨论】:

  • 如果你打算支持stackinsert_iterator 将不起作用。而string 也有push_backinsert_iterator 不会调用,但back_inserter 会调用。 insert_iterator 调用 insert,与 push_back 一样,vectorstring 都支持,但 stack 不支持。
  • @BenjaminLindley:哦,嗯,有趣的一点。所以你认为我应该只引用容器并调用reservepush_back,而不使用迭代器? (我可能会忽略stack...嗯)
  • 在这一点上,我对你应该做什么的看法并不可靠。我还在考虑。我只是指出,您对标准接口(如果您想包含堆栈)的需求不满足您的要点中的两个选项。
  • @BenjaminLindley:啊,我明白了。让我稍微编辑一下这个问题......我认为stack 过于严格。
  • 为什么不让调用者选择性地提供一个 lambda 来调用给定对象和大小?

标签: c++ stl iterator buffer


【解决方案1】:

您可以创建带有迭代器的非常通用的函数,然后创建一系列更专业的函数来获取各种序列容器类型(向量、列表、双端队列、字符串),并在转发到更通用的函数之前采取适当的操作,例如:

template<typename OutputIterator>
fill_buffer_iterator_version(OutputIterator it)
{
    // fill data through output iterator
} 

// default generic version uses back_inserter, all standard
// sequence containers support push_back
template<typename Container>
fill_buffer(Container & c)
{
    fill_buffer_iterator_version(std::back_inserter(c));
}

// specialize for vector   
fill_buffer(std::vector<char> & v)
{
    v.reserve(100);
    fill_buffer_iterator_version(std::back_inserter(v));
}

【讨论】:

  • 呃,这会创建 so 我函数的许多副本...但至少它会起作用,+1 我猜
【解决方案2】:

你知道你要读取多少字节,所以在调用fread之前使用resize方法。将begin 传递给它。或者,在自定义(模板化)版本中,您可以传递容器(通过引用),在“文件读取”之前为其分配内存并执行相同的操作。

【讨论】:

  • 如果用户给了我一些不支持resize的东西,比如(比如)list
猜你喜欢
  • 2011-09-07
  • 2012-02-04
  • 2014-12-09
  • 1970-01-01
  • 2015-03-07
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
相关资源
最近更新 更多