为什么`copy_n`,`fill_n`和`generate_n`?

时间:2014-03-13 15:09:05

标签: algorithm c++11 stl standards stl-algorithm

为什么{+ 1}},_ncopy的{​​{1}}版本已在C ++ 11中提供,为什么只有这些算法?

3 个答案:

答案 0 :(得分:3)

我们以std::generate()std::generate_n()为例。前者需要ForwardIterator s,指向范围的开始和结束,后者为OutputIterator。这具有微妙的含义,例如:

#include <algorithm>
#include <vector>

int main() {

  std::vector<int> v;

  v.resize(5); // <-- Elements constructed!!!

  std::generate(v.begin(), v.end(), [](){ return 42; });

  std::vector<int> w;

  w.reserve(5); // Space only reserved but not initialized

  std::generate_n(std::back_inserter(w), 5, [](){ return 42; });

}

这足以让我证明这两个版本的存在。

在许多用例中,你绝对正确,这些功能的功能重叠,其中一个可能看起来多余。

  

为什么只有这些算法?

可能是因为没有人为其他算法提出_n版本。在TemplateRex关联时,也可能有std::iota_n()What would be a good implementation of iota_n (missing algorithm from the STL)

答案 1 :(得分:3)

一般来说, STL只提供原语,人们可以从中定义适当的变体。

SGI文档提供了以下提供例外情况的理由:

  • copy_n适用于不是前向迭代器的输入迭代器。

  • fill_ngenerate_n适用于不是前向迭代器的输出迭代器。

正如@Jared Hoberock在评论中指出的那样,<memory>标题还包含uninitialized_copy_n版本的fill_n版本,这些版本已经过优化已知的。

C ++ 11提供了一些其他的便利包装器(例如find_if_not),但是对于lambda谓词,这样的包装器变得更容易自己编写。

注意:还有一个search_n,但它的语义与search不同,因为后者会查看两个输入范围之间的重叠,前者会看连续来自单一输入范围的元素。

答案 2 :(得分:3)

Alexander Stepanov(STL的原设计师)在他出色的视频系列Efficient Programming with Components中讨论了这个问题(以及其他许多问题)。他最初提出了许多其他_n变体的STL算法,但是当STL最初标准化时它们不被接受。有些人已经加入了C ++ 11,但仍然有一些他认为应该可用的东西缺失。

有很多原因可以解释为什么_n变体的算法很有用。你可能有一个输入迭代器或输出迭代器,你知道它可以产生或消耗n个元素,但是你没有办法获得合适的结束迭代器。你可能有一个类似于列表的容器类型,你知道它对于一个操作来说足够大,但它并没有给你一个有效的方法来获得一个超出你的开始迭代器的迭代器位置。你可能有像binary_search / lower_bound这样的算法,它最自然地用计数范围表示。当你已经拥有n但是你没有结束迭代器并且必须生成一个来调用算法的非_n变体时,它可能会更方便。