Я просто хотел знать, как реализована deque и как выполняются основные операции, такие как В этой реализации предусмотрены push_front и оператор произвольного доступа.
Возможный дубликат Что такое дек в STL?
@Someprogrammerdude, если бы он был реализован как «список» массивов, постоянный произвольный доступ был бы невозможен. Обычно это массив указателей на массивы с данными.
I just wanted to know how deque is implemented
Всегда полезно иметь предлог для создания 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 |
+-------------------------------------------------------------+
how are the basic operations like
push_front
and random access operator are provided in that implementation?
Во-первых, 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
здесь должен быть размер одного подмассива.
Из эта
std::deque
ссылка: «типичные реализации используют последовательность отдельно выделенных массивов фиксированного размера». Короче говоря, это список массивов.