C++ 如何实现非连续容器(如std::deque)的随机访问迭代器?
我了解随机访问迭代器如何用于连续容器,如C++ 如何实现非连续容器(如std::deque)的随机访问迭代器?,c++,iterator,deque,random-access,C++,Iterator,Deque,Random Access,我了解随机访问迭代器如何用于连续容器,如std::vector:迭代器只维护指向当前元素的指针,任何加减操作都应用于指针 然而,对于如何为非连续容器实现类似的功能,我感到困惑。我对std::deque:iterator工作原理的第一个猜测是,它维护一个指向它所包含的连续内存组的表的指针,但我不确定 典型的标准库如何实现这一点?您可以使用std::vector大致满足std::deque的要求。加上一个低/高水位线,告诉你第一个/最后一个元素在哪里。(对于一个定义了N的实现,它可能随T而变化,st
std::vector
:迭代器只维护指向当前元素的指针,任何加减操作都应用于指针
然而,对于如何为非连续容器实现类似的功能,我感到困惑。我对std::deque:iterator
工作原理的第一个猜测是,它维护一个指向它所包含的连续内存组的表的指针,但我不确定
典型的标准库如何实现这一点?您可以使用
std::vector
大致满足std::deque
的要求。加上一个低/高水位线,告诉你第一个/最后一个元素在哪里。(对于一个定义了N的实现,它可能随T
而变化,std::array
s实际上是正确对齐的未初始化内存块,而不是std::array
s,但是您知道了)
使用通常的指数增长,但在正面和背面
查找只需执行(index+first)/N
和%N
即可查找块和子元素
这比std::vector查找更昂贵,但是是O(1)。可以通过存储指向引用值的指针和指向该值所在的连续内存块的双指针来实现deque迭代器。双指针指向deque管理的块的连续指针数组
class deque_iterator
{
T* value;
T** block;
…
}
因为value
和block
都指向连续内存,所以可以实现诸如在恒定时间内查找迭代器之间的距离之类的操作(示例改编自libc++)
请注意,虽然
值
不会因向前推
和向后推
等操作而无效,块
可能是无效的,这就是为什么deque\u迭代器
会因此类操作而无效。谁说deque
是不连续的?它通常被实现为一个动态数组。@ooga from与std::vector相反,deque的元素不是连续存储的:典型的实现使用一系列单独分配的固定大小数组。
@ooga,那么它与vector有何不同?@BryanChen我想知道这是什么意思?一个“数组序列”?一个典型的deque
:的图表和一篇看起来可能有用的文章(尽管我只看了一眼):deque::push_back页面表示恒定时间复杂度,vector::push_back页面表示摊销恒定时间复杂度。使用向量作为数组指针的后端会不会违反deque::push_back为常量的要求?还是摊销常数可以接受?@mebob在其他地方指出摊销常数:是错误的。我应该在确认符合标准后修复它。好的,这是有意义的。无论如何,我真的想不出一个绕过摊销常数限制的方法。回到我关于迭代器的问题:那么迭代器只需保存对所述向量的引用,并在到达1的末尾时切换缓冲区?@mebob是的,类似于这样。您可能还需要添加这一点,使N
成为一个编译时常量,也是2的幂(可能是静态断言
)这是目前为止唯一能回答这个问题的答案,而且肯定是一个很好的答案。
difference_type operator-(deque_iterator const& x, deque_iterator const& y)
{
return (x.block - y.block) * block_size
+ (x.value - *x.block)
- (y.value - *y.block);
}