简体   繁体   English

如何实现非连续容器(例如std :: deque)的随机访问迭代器?

[英]How are random access iterators for non-contiguous containers (such as std::deque) implemented?

I understand how random access iterators work for contiguous containers like std::vector : the iterator simply maintains a pointer to the current element and any additions/subtractions are applied to the pointer. 我理解随机访问迭代器如何对连续容器(如std::vector起作用:迭代器只是维护一个指向当前元素的指针,并且任何加法/减法都应用于指针。

However, I'm baffled as to how similar functionality could be implemented for a non-contiguous container. 但是,我对于如何为非连续容器实现类似的功能感到困惑。 My first guess for how std::deque:iterator works, is that it maintains a pointer to some table of the groups of contiguous memory it contains, but I'm not sure. 我对std::deque:iterator如何工作的第一个猜测是,它维护了一个指向它包含的连续内存组的表的指针,但我不确定。

How would a typical standard library implement this? 典型的标准库如何实现这一点?

You can satisfy the requirememts of a std::deque with a std::vector<std::unique_ptr<std::array<T,N>>> roughly. 你可以用std::vector<std::unique_ptr<std::array<T,N>>>粗略地满足std::deque的requirememts。 plus a low/high water mark telling you where the first/last elements are. 加上一个低/高水印,告诉你第一个/最后一个元素在哪里。 (for an implementation defined N that could vary with T , and the std::array s are actually blocks of properly aligned uninitialized memory and not std::array s, but you get the idea). (对于一个实现定义的N可能随T而变化,而std::array实际上是正确对齐的未初始化内存的块而不是std::array s,但你明白了)。

Use usual exponential growth, but on both front and back. 使用通常的指数增长,但在正面和背面。

Lookup simply does (index+first)/N and %N to find the block and sub element. Lookup只是(index+first)/N%N来查找块和子元素。

This is more expensive than a std::vector lookup, but is O(1). 这比std::vector查找更昂贵,但是是O(1)。

A deque iterator can be implemented by storing both a pointer to the referenced value and a double pointer to the contiguous block of memory in which that value is located. deque迭代器可以通过存储指向引用值的指针和指向该值所在的连续内存块的双指针来实现。 The double pointer points into a contiguous array of pointers to blocks managed by the deque. 双指针指向由deque管理的块的连续指针数组。

class deque_iterator
{
  T* value;
  T** block;
  …
}

Because both value and block point into contiguous memory, you can implement operations such finding the distance between iterators in constant time (example adapted from libc++). 因为valueblock指向连续的内存,所以可以实现诸如在常量时间内查找迭代器之间的距离的操作(例如,从libc ++改编的​​示例)。

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);
}

Note that, while value will not be invalidated by operations such as push_front and push_back , block might be, which is why deque_iterator is invalidated by such operations. 请注意,虽然push_frontpush_back等操作不会使value无效,但可能是block ,这就是deque_iterator被此类操作无效的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM