- Hybryda listy oraz wektora
-
deque
dzieli się na kawałki (ang. chunk), które są tablicami porozrzucanymi po pamięci - Rozmiar takiego kawałka zależy od kompilatora i implementacji biblioteki standardowej (nie ma jednej reguły)
-
Dodatkowo deque posiada jeszcze jeden wektor, który przechowuje wskaźniki wskazujące początek każdego
chunka
w pamięci. -
W ten sposób zyskujemy 2 rzeczy:
- Dodawanie nowego elementu jest szybsze, bo alokujemy co najwyżej pamięć dla jednego, całego
chunka
i nie będziemy przenosić elementów jak wstd::vector<T>
, gdy zabraknie nam miejsca na alokacje dodatkowej pamięci - Dane załadowane z jednego
chunka
są cache-friendly
- Dodawanie nowego elementu jest szybsze, bo alokujemy co najwyżej pamięć dla jednego, całego
-
Częściowo cache-friendly, czyli poszczególne
chunki
znajdą się w pamięci podręcznej procesora -
Typ
T
może być dowolny. Zarówno typ wbudowany jakint
,double
, jak i własny zdefiniowany przez nas typ -
Każdy
chunk
jest reprezentowany w pamięci jak tablica, natomiast samechunki
nie sąsiadują ze sobą i są porozrzucane jak węzły listy -
Dodanie nowego elementu jest szybkie
- Jeżeli dany
chunk
ma jeszcze miejsce to dopisujemy go na koniec - Jeżeli nie, to alokowany jest nowy chunk i tam wpisywany jest nowy element
- Jeżeli dany
-
Usuwanie z początku i końca jest szybkie, bo powoduje jedynie przesunięcie iteratorów
begin()
lubend()
- Usuwanie elementów ze środka jest kosztowne
-
Odczyt i modyfikacja jest szybka
- Znamy rozmiar
chunka
, więc wiemy dokładnie, z którego pola w naszym wektorze pomocniczym powinniśmy odczytać adreschunka
- Wiemy także, z którego pola odczytać daną, gdyż
chunk
jest ułożony jak tablica.
- Znamy rozmiar
Matematycznie ujmując: jeżeli chunk
ma 16 elementów a my chcemy dostać się do 100 elementu to:
x = 100 / 16 -> x = 6
(ucinamy część po przecinku)y = 100 % 16 -> y = 4
Zatem wiemy, że jest to 4-ty element w 6-tym chunku
.
Ta wiedza jest zupełnie niepotrzebna przy użytkowaniu std::deque
. Kontener zajmuje się tym automatycznie.
Operacje | Metody |
---|---|
dodawanie elementu | push_back() , emplace_back() , push_front() , emplace_front() , insert() , emplace() |
modyfikowanie/dostęp do elementu | at() , operator[] |
pierwszy/ostatni element | back() , front() |
rozmiar | size() |
wyczyszczenie nieużywanej pamięci | shrink_to_fit() , |
odwrócony (ang. reverse) iterator | rbegin() , rend() |
stały iterator | cbegin() , cend() , crbegin() , crend() |
wyczyszczenie kontenera | clear() |
przygotowanie elementu do usunięcia | remove() (nie jest metodą std::deque ), |
wymazanie elementów z pamięci | erase() |
#include <iostream>
#include <deque>
int main() {
std::deque<int> d = {7, 5, 16, 8};
d.push_front(13);
d.push_back(25);
for(const auto& n : d) {
std::cout << n << ' ';
}
std::cout << '\n';
}
Output:
13 7 5 16 8 25
- Znajdź dokumentację
std::deque
na cppreference.com - Stwórz nowy plik i napisz funkcję
main()
- Stwórz pusty
deque
- Dodaj do niego 5 dowolnych wartości
- Wyświetl
deque
- Usuń 2-gi i 4-ty element
- Dodaj na początek i koniec wartość 30
- Wyświetl
deque
- Dodaj na 4 pozycji liczbę 20
- Wyświetl
deque