Особенность размещение элементов в std::deque

128
23 марта 2019, 04:40
#include <iostream>
#include <deque>
int main()
{
    std::deque<int>d{ 0,1,2,3,4,5,6,7,8,9 };
    for (auto & i : d)
        std::cout << i << ":" << &i << std::endl;
    return 0;
}

output:

0:0054FB78

1:0054FB7C

2:0054FB80

3:0054FB84

4:00550288

5:0055028C

6:00550290

7:00550294

8:005502C8

9:005502CC

Можно сделать вывод, что элементы размещены следующим видом

|0 1 2 3|->|4 5 6 7|->|8 9 ...

то есть кусками по 4 элемента.

В чем преимущество данной реализации?

Answer 1

Дек должен обеспечить компромисс между быстрым добавлением в конец и снятием элемента из начала (доступ за O(1)) и легким расширением. Это можно обеспечить при хранении очереди в циклическом виде в динамическом массиве, который при необходимости расширяется

При увеличении размера умножением на определенный коэффициент (например, 2) обеспечивается амортизированная сложность расширения O(1) на элемент, однако при этом могут быть моменты довольно долгой перезаписи. Кроме того, такой подход требует выделения единого куска памяти (возможно - большого).

Так устроен vector. Ему требуется обеспечивать быстрый доступ к произвольному элементу, а перед деком такой задачи не стоит.

Видимо, с целью избавления от этих недостатков выбран метод хранения дека в наборе чанков определённого размера, указатели на которые лежат в векторе.

Картинка отсюда

cppreference

The storage of a deque is automatically expanded and contracted as needed. Expansion of a deque is cheaper than the expansion of a std::vector because it does not involve copying of the existing elements to a new memory location.

Answer 2

В отличии класса std::list где элементы хранятся поодиночке, преимущество - запись

0->1->2->3

И вектора std::vector где элементы хранятся вместе, преимущество - чтение

[0, 1, 2, 3]

Класс std::deque предлагает среднее меджу вышеуказаными, он хранит данные в "кусках" и является компромиссом. Cкорость чтения и записи что-то "среднее" этими двумя потому-что ему не приходится итерироватся по каждому элементу одновременно не приходится пересоздавать весь массив для вставки новых элементов.

[0, 1, 2, 3]->[4, 5, 6, 7] 
Answer 3

std::deque логичнее всего реализовывать как двунаправленный список, т.е. каждый элемент содержит два указателя - на предыдущий и последующий элементы. На современный компьютерах указатели 64-х битные, итого 16 байт. Было бы обидно на каждый 4 байта int иметь 16 байт служебной информации, т.е. КПД 20%. Упаковывая по 4 значения в один элемент мы доводим КПД до 50%

READ ALSO
При вызове метода ничего не происходит.С++

При вызове метода ничего не происходит.С++

При вызове метода about(); на любом обьекте ничего не происходит только завершаеться программаХотя метод fiiling(); работает корректно

189
Разложить число на множители

Разложить число на множители

Дано натуральное число nПолучить его каноническое разложение (разложение на простые множители)

151
Изменение размеров виджетов

Изменение размеров виджетов

Как изменить размеры виджетов которые находятся в слое(layout), получается изменить размеры кнопок через qss(пока я что попробовал), но размеры...

148
Прекращена работа программы. Как вы ее исправили-бы

Прекращена работа программы. Как вы ее исправили-бы

Всем привет, начал разработку игры, еще мало чего создал, но после добавления отклика на столкновение почти сразу после запуска exe виндовс...

166