顺序容器和迭代器算术

sequential containers and iterators arithmetic

本文关键字:迭代器 顺序      更新时间:2023-10-16

我正在研究顺序容器库,有些事情让我思考。

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

我不明白这个约束。例如,禁止我们在两个迭代器之间减法或向迭代器添加 int 的原因是什么?毕竟,如果我们可以访问前/后递增/递减,我们可以很容易地通过使用整数计数器重复迭代这些操作来实现加法和减法,即使效率低下。

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

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

您在问题中提到了原因:

。即使效率低下...

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

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


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