【问题标题】:sequential containers and iterators arithmetic顺序容器和迭代器算术
【发布时间】:2019-01-30 19:52:03
【问题描述】:

我正在研究顺序容器库,有些事情让我想到了。

我已经理所当然地认为每个容器,除了特殊情况,如 forward_list,它不可能在一个方向上,完全支持迭代器算术。相反,我刚刚发现通用容器仅支持一组非常特定的操作:* 和 ->(出于显而易见的原因)、前后递增和递减(不是 100% 确定 post)和等式/不等式关系运算符。为向量、字符串和双端队列保留更复杂的算术。

我不明白这个限制。我们被禁止的原因是什么,例如,在两个迭代器之间进行减法或在迭代器中添加一个 int?毕竟,如果我们可以访问前/后自增/自减,即使效率低下,我们也可以通过使用整数计数器重复迭代这些操作来轻松实现加法和减法。

【问题讨论】:

  • 你回答了你自己的问题:"...我们可以轻松,即使效率低下..." 。如果你想这样做,你可以,但标准容器试图让你知道这可能是一个坏主意。
  • 有不同的iterator categories。在非随机访问迭代器上,算术被禁用(可能),因为它通常具有非常量的复杂性,并且如果使用不当可能会减慢您的程序。要对任意迭代器进行算术运算,请使用std::nextstd::prevstd::advancestd::distance 等。
  • “轻松,即使效率低下”,这正是关键所在。 C++ 不希望低效的东西容易与高效的东西混淆。
  • 您可能还想了解std::nextstd::prevstd::advancestd::distance,以获得不涉及直接指针/迭代器算法的通用解决方案。只是说。

标签: c++ iterator containers


【解决方案1】:

您提到的缺失的低效操作实际上是可用的,由std::distancestd::advance 提供。 (还有std::prevstd::next,出于更微妙的原因。)

不要求所有迭代器或至少所有双向迭代器都支持operator+= 之类的东西的原因是警告用户他们正在做的事情没有他们预期的那么有效。在循环中编写类似*(iter+offset) 的内容很容易,然后将容器类型从std::vector 更改为std::set,并且不会注意到您不小心将O(n) 操作变成了O(n^2) 操作。

【讨论】:

  • +1。我怀疑也可以通过模板元编程根据调用者提供的迭代器是否直接支持某些操作来选择不同的算法。
  • @davmac 是的。例如,std::distance 是随机访问迭代器的常数时间,使用 std::iterator_traits 来决定它正在查看哪种迭代器。这是模板元编程和部分模板专业化的原始用途之一。
  • @davmac 那里(通常)不需要。元编程已经在std::next 等内完成。
  • @davmac 扩展我之前的评论:您需要模板元编程的一个例子是区分非前向输入迭代器。例如,如果您想将范围复制到容器中,并且能够根据范围的长度预先保留内存,则使用std::distance 在语法上是有效的,但对于非转发在逻辑上是错误的迭代器,因为您不能再进行复制,因为不保证非前向迭代器允许多次传递。我希望实现一个向量来检查这一点。
  • @user2079303 我的观点是,可以区分迭代器的能力,并根据其能力对算法或函数进行不同的实现(不管是由用户完成还是在就我而言,标准库实现)。
【解决方案2】:

您在问题中提到了原因:

...即使效率低下...

在算子中不执行计算复杂(通常是线性或更差)的操作是一个很好的设计。这种设计允许 API 的用户假设加法和减法运算具有恒定的复杂性,而无需知道该运算的规范。如果这样的假设是错误的,程序员很容易最终编写出比预期更复杂的渐近复杂度的程序。

此类线性运算以std::nextstd::distance 等形式存在。程序员不会(或不应该)在不知道函数规范的情况下假设函数调用的复杂性。


如果您不同意标准库的设计,您可以编写一个迭代器适配器,它会添加缺少的运算符重载,然后使用它。

【讨论】:

  • 该标准确实指定了很多“函数调用”的复杂性。包括std::next()(线性复杂度),以及相当多的标准算法。根据定义,允许程序员假设实现符合该规范。
  • @Peter 程序员确实可以假设实现符合其规范。我打算传达程序员可以/或不能在没有上下文的情况下做出假设。规范就是这种上下文的一个例子。我会尽量说得更清楚。
猜你喜欢
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
  • 1970-01-01
  • 2015-10-24
  • 2013-11-25
  • 2020-10-05
  • 2017-01-03
相关资源
最近更新 更多