【问题标题】:How are random access iterators for non-contiguous containers (such as std::deque) implemented?非连续容器(例如 std::deque)的随机访问迭代器是如何实现的?
【发布时间】:2014-06-06 05:53:00
【问题描述】:

我了解随机访问迭代器如何为std::vector 之类的连续容器工作:迭代器只维护一个指向当前元素的指针,并且任何加法/减法都应用于该指针。

但是,我对如何为非连续容器实现类似功能感到困惑。我对std::deque:iterator 工作原理的第一个猜测是,它维护了一个指向它包含的连续内存组的某个表的指针,但我不确定。

典型的标准库将如何实现这一点?

【问题讨论】:

  • 谁说deque 不连续?它通常实现为动态数组。
  • @ooga from here As opposed to std::vector, the elements of a deque are not stored contiguously: typical implementations use a sequence of individually allocated fixed-size arrays.
  • @ooga,那它和向量有什么不同呢?
  • @BryanChen 我想知道这是什么意思?一个“序列......数组”?
  • 一个典型的deque 的图表:kremer.cpsc.ucalgary.ca/STL/1024x768/deque.html 和一篇看起来可能有帮助的文章(虽然我只是看了一眼):secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/deques/page/…

标签: c++ iterator deque random-access


【解决方案1】:

双端队列迭代器可以通过存储一个指向引用值的指针和一个指向该值所在的连续内存块的双指针来实现。双指针指向由双端队列管理的块的连续指针数组。

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

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

请注意,虽然value 不会被push_frontpush_back 等操作失效,但block 可能会,这就是deque_iterator 会被此类操作失效的原因。

【讨论】:

  • 这是迄今为止唯一能回答这个问题的答案,而且绝对是一个很好的答案。
【解决方案2】:

您可以大致满足std::dequestd::vector<std::unique_ptr<std::array<T,N>>> 的要求。加上一个低/高水位线,告诉您第一个/最后一个元素在哪里。 (对于定义的 N 可能随 T 变化的实现,std::arrays 实际上是正确对齐的未初始化内存块,而不是 std::arrays,但你明白了)。

使用通常的指数增长,但在正面和背面。

查找只是通过(index+first)/N%N 来查找块和子元素。

这比 std::vector 查找更昂贵,但是 O(1)。

【讨论】:

  • http://cppreference.com deque::push_back 的页面表示恒定时间复杂度,而 vector::push_back 的页面表示摊销的恒定时间复杂度。使用向量作为指向数组的指针的后端不会违反 deque::push_back 是常量的要求吗?还是摊销常数可以接受?
  • @mebob 在其他地方声明摊销常数:是错误的。我应该在与标准确认后修复它。
  • 好吧,这是有道理的。无论如何,我真的想不出一种方法来绕过摊销常数限制。回到我关于迭代器的问题:所以迭代器会简单地持有对所述向量的引用并在到达一个末尾时切换缓冲区?
  • @mebob 是的,类似的。
  • 您可能还想补充一点,将 N 设为也是 2 的幂的编译时常量(也许是 static_assert)应该对性能非常有利。
猜你喜欢
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 2017-10-15
  • 2018-07-07
  • 2015-05-13
  • 1970-01-01
  • 2019-12-06
相关资源
最近更新 更多