顺序容器和迭代器算术
sequential containers and iterators arithmetic
我正在研究顺序容器库,有些事情让我思考。
我理所当然地认为,除了特殊情况,如forward_list,在一个方向上是不可能的,每个容器都完全支持迭代器算术。相反,我刚刚发现通用容器仅支持一组非常具体的操作:* 和 ->(出于显而易见的原因(、前后递增和递减(不是 100% 确定后(和相等/不等关系运算符。更复杂的算术保留用于向量、字符串和 deque。
我不明白这个约束。例如,禁止我们在两个迭代器之间减法或向迭代器添加 int 的原因是什么?毕竟,如果我们可以访问前/后递增/递减,我们可以很容易地通过使用整数计数器重复迭代这些操作来实现加法和减法,即使效率低下。
您提到的缺失的低效操作实际上是可用的,由std::distance
和std::advance
提供。(还有std::prev
和std::next
,原因更微妙。
不要求所有迭代器或至少所有双向迭代器来支持诸如operator+=
之类的东西的原因是为了警告用户他们正在做的事情并不像他们预期的那么有效。很容易在循环中编写类似*(iter+offset)
的东西,然后将容器类型从std::vector
更改为std::set
,并且不会注意到您不小心将O(n)
操作变成了O(n^2)
操作。
您在问题中提到了原因:
。即使效率低下...
这是一个很好的设计,不会在运算符中执行计算复杂的(通常是线性或更糟的(运算。此设计允许 API 的用户假定加法和减法运算具有恒定的复杂性,而无需知道该操作的规范。如果这样的假设是错误的,程序员很容易最终编写出比他们预期的更糟糕的渐近复杂性的程序。
这种线性运算以std::next
、std::distance
等形式存在,程序员不会(或不应该(在不知道函数规范的情况下对函数调用的复杂性做出假设。
如果您不同意标准库的设计,可以编写一个迭代器适配器,该适配器添加缺少的运算符重载,并使用它。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 顺序容器和迭代器算术
- 在C++中,是否可以在单个循环中顺序迭代多个迭代器
- 确定设置迭代器的顺序
- 二进制搜索树中按顺序遍历的复杂性(使用迭代器)
- 迭代器是否以相同的顺序迭代 boost::unordered_set 或 boost::unordered_map 只要集合不变?
- 如何编写一个迭代器包装器来组合底层迭代器中的顺序值组
- 按顺序比较C++迭代器安全吗
- 试图让Vector迭代器以不同的顺序进行迭代