【问题标题】:Why is there a separation of algorithms, iterators and containers in C++ STL为什么在 C++ STL 中有算法、迭代器和容器的分离
【发布时间】:2012-08-10 10:34:38
【问题描述】:

我不明白为什么他们在 C++ STL 中分离了算法、迭代器和容器。如果到处都大量使用模板,那么我们可以让类将所有东西放在一个带有模板参数的地方。

我得到的一些文本解释说,迭代器有助于算法与容器数据进行交互,但如果容器公开一些机制来访问它拥有的数据呢?

【问题讨论】:

  • 我一个字都听不懂。 :(
  • 好吧,很抱歉造成的混乱,我的意思是我们有不同的容器类、迭代器等。我想弄清楚如果我们使用模板将所有内容放在一个类中会出现什么问题,容器有数据并且它们可以暴露一些接口来查看或修改。为什么他们是分开的?我的意思是为什么会有不同的迭代器、算法等。
  • This question 可能会给你一些建议。 This interview 与 STL 的创建者 Alex Stephanov 也包含一些见解。
  • 这个问题可能措辞不明确,但这是一个真实的问题。答案是 M 容器 + N 算法通常需要 M * N 代码段,但迭代器充当“胶水”,您只能拥有 M + N 代码段。
  • @rhalbersma:投票支持重新开放,您的评论是我自己能想到的最佳答案。

标签: c++ algorithm stl iterator containers


【解决方案1】:

使用M 容器+N 算法,通常需要M * N 段代码,但使用充当“胶水”的迭代器,这可以简化为M + N 段代码。

示例:在 3 个容器上运行 2 个算法

std::list<int> l = { 0, 2, 5, 6, 3, 1 }; // C++11 initializer lists
std::vector<int> v = { 0, 2, 5, 6, 3, 1 };  // C++11 initializer lists
std::array<int, 5> a = { 0, 2, 5, 6, 3, 1 };

auto l_contains1 = std::find(l.begin(), l.end(), 1) != l.end();
auto v_contains5 = std::find(v.begin(), v.end(), 5) != v.end();
auto a_contains3 = std::find(a.begin(), a.end(), 3) != a.end();

auto l_count1 = std::count(l.begin(), l.end(), 1);
auto v_count5 = std::count(v.begin(), v.end(), 5);
auto a_count3 = std::count(a.begin(), a.end(), 3);

您只调用了 2 种不同的算法,并且只有 3 个容器的代码。每个容器将 begin()end() 迭代器传递给容器。即使您有3 * 2 行代码来生成答案,也只有3 + 2 部分功能需要编写。

对于更多的容器和算法,这种分离极大地减少了代码中的组合爆炸,否则会出现:STL 中有 5 个序列容器、8 个关联容器和 3 个容器适配器,并且在 STL 中有近 80 个算法&lt;algorithm&gt; 单独(甚至不包括 &lt;numeric&gt; 中的那些)所以你只有 16 + 80 而不是 16 * 80,代码减少了 13 倍! (当然,并不是每个算法都对每个容器都有意义,但重点应该很清楚)。

迭代器可以分为 5 类(输入、输出、转发、双向和随机访问),一些算法会根据迭代器的能力委托给专门的版本。这将在一定程度上减少代码减少,但通过选择最适合手头的迭代器的算法来大大提高效率。

请注意,STL 在分离方面并不完全一致:std::list 有自己的 sort 成员函数,它使用特定于实现的细节来对自己进行排序,而std::string 有大量的成员函数算法,大部分可以作为非成员函数实现。

【讨论】:

    猜你喜欢
    • 2014-12-05
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2021-02-14
    • 2010-10-17
    相关资源
    最近更新 更多