【问题标题】:How is deque implemented in c++ stlc++ stl中deque是如何实现的
【发布时间】:2019-10-12 18:34:52
【问题描述】:

我只是想知道deque是如何实现的,以及该实现中如何提供push_front和随机访问运算符等基本操作。

【问题讨论】:

  • 来自this std::deque reference:“典型的实现使用一系列单独分配的固定大小的数组”。简而言之,就是一个数组列表。
  • @Someprogrammerdude 如果它被实现为数组的“列表”,则不可能进行恒定的随机访问。通常它是一个指向包含数据的数组的指针数组。

标签: c++ stl deque


【解决方案1】:

我只是想知道双端队列是如何实现的

为 ASCII 艺术找个借口总是好的:

+-------------------------------------------------------------+                       
| std::deque<int>                                             |                       
|                                                             |                       
|  subarrays:                                                 |                       
| +---------------------------------------------------------+ |                       
| |           |           |           |         |           | |                       
| | int(*)[8] | int(*)[8] | int(*)[8] |int(*)[8]|int(*)[8]  | |                       
| |           |           |           |         |           | |                       
| +---------------------------------------------------------+ |                       
|                        /            \                       |                       
|                       /              \                      |                       
|                      /                \                     |                       
|                     /                  \                    |                       
|                    /                    \                   |                       
|                   /                      \                  |                       
|                  /                        \                 |                       
|                 /                          \                |                       
|                -                            -               |                       
|               +------------------------------+              |                       
|               | ?, ?, 42, 43, 50, ?, ?, ?, ? |              |                       
|               +------------------------------+              |                       
|                                                             |
| additional state:                                           |                       
|                                                             |                       
| - pointer to begin of the subarrays                         |                       
| - current capacity and size                                 |                       
| - pointer to current begin and end                          |                       
+-------------------------------------------------------------+                       

在该实现中如何提供push_front 和随机访问运算符等基本操作?

首先,std::deque::push_front,来自 libcxx:

template <class _Tp, class _Allocator>
void
deque<_Tp, _Allocator>::push_front(const value_type& __v)
{
    allocator_type& __a = __base::__alloc();
    if (__front_spare() == 0)
        __add_front_capacity();
    __alloc_traits::construct(__a, _VSTD::addressof(*--__base::begin()), __v);
    --__base::__start_;
    ++__base::size();
}

这显然是检查前面已经分配的内存是否可以容纳一个额外的元素。如果没有,它会分配。然后,主要的工作转移到迭代器上:_VSTD::addressof(*--__base::begin()) 比容器的当前前端元素先移动一个位置,并将这个地址传递给分配器,通过复制 v(默认分配器)来构造一个新元素。肯定会做一个展示位置-new)。

现在随机访问。同样来自 libcxx,std::deque::operator[](非const 版本)是

template <class _Tp, class _Allocator>
inline
typename deque<_Tp, _Allocator>::reference
deque<_Tp, _Allocator>::operator[](size_type __i) _NOEXCEPT
{
    size_type __p = __base::__start_ + __i;
    return *(*(__base::__map_.begin() + __p / __base::__block_size) + __p % __base::__block_size);
}

这几乎是计算相对于某个起始索引的索引,然后确定子数组和相对于子数组开始的索引。 __base::__block_size 这里应该是一个子数组的大小。

【讨论】:

    猜你喜欢
    • 2014-08-03
    • 2023-03-09
    • 2019-05-08
    • 2013-05-08
    • 2011-04-18
    • 2021-06-22
    • 2011-11-26
    • 2023-03-27
    • 2023-01-15
    相关资源
    最近更新 更多