QVector
jest w większości analogiczny do std::vector
, jak można się domyślić z nazwy. QList
jest bliżej boost::ptr_deque
, pomimo pozornego skojarzenia z std::list
. Nie przechowuje obiektów bezpośrednio, ale zamiast tego przechowuje do nich wskaźniki. Zyskujesz wszystkie korzyści wynikające z szybkiego wstawiania na obu końcach, a realokacje obejmują tasowanie wskaźników zamiast konstruktorów kopiujących, ale tracisz lokalność przestrzenną rzeczywistego std::deque
lub std::vector
i zyskujesz dużo alokacji sterty. Ma pewne decyzje, aby uniknąć alokacji sterty dla małych obiektów, odzyskać lokalność przestrzenną, ale z tego, co rozumiem, dotyczy to tylko rzeczy mniejszych niż int
.
QLinkedList
jest analogiczny do std::list
i ma wszystkie wady. Ogólnie rzecz biorąc, powinien to być Twój ostatni wybór pojemnika.
Biblioteka QT bardzo sprzyja używaniu QList
obiektów, więc faworyzowanie ich we własnym kodzie może czasami uniknąć niepotrzebnej nudy. Dodatkowe użycie sterty i losowe rozmieszczenie rzeczywistych danych może teoretycznie zaszkodzić w niektórych okolicznościach, ale często jest niezauważalne. Sugerowałbym więc używanie, QList
dopóki profilowanie nie zasugeruje zmiany na QVector
. Jeśli spodziewasz się, że ciągła alokacja będzie ważna [czytaj: łączysz się z kodem, który oczekuje a T[]
zamiast a QList<T>
], może to być również powód, aby zacząć od QVector
razu.
Jeśli pytasz ogólnie o kontenery i właśnie użyłeś dokumentów QT jako odniesienia, powyższe informacje są mniej przydatne.
An std::vector
to tablica, której rozmiar można zmieniać. Wszystkie elementy są przechowywane obok siebie i masz szybki dostęp do poszczególnych elementów. Wadą jest to, że wstawki są skuteczne tylko na jednym końcu. Jeśli umieścisz coś w środku lub na początku, musisz skopiować inne obiekty, aby zrobić miejsce. W notacji duże-o, wstawienie na końcu to O (1), wstawienie gdziekolwiek indziej to O (N), a dostęp swobodny to O (1).
An std::deque
jest podobny, ale nie gwarantuje, że obiekty są przechowywane obok siebie i umożliwia wstawianie na obu końcach O (1). Wymaga również jednoczesnego przydzielania mniejszych fragmentów pamięci, co czasami może być ważne. Dostęp losowy to O (1), a wstawienie w środku to O (N), tak samo jak w przypadku a vector
. Lokalność przestrzenna jest gorsza niżstd::vector
, ale obiekty są zwykle skupione, więc zyskujesz pewne korzyści.
Lista std::list
jest połączona. Wymaga największego narzutu pamięci spośród trzech standardowych kontenerów sekwencyjnych, ale oferuje szybkie wstawianie w dowolnym miejscu ... pod warunkiem, że wiesz z wyprzedzeniem, gdzie należy wstawić. Nie oferuje losowego dostępu do poszczególnych elementów, więc musisz iterować w O (N). Ale kiedy już tam jest, rzeczywiste wstawienie to O (1). Największą korzyścią std::list
jest to, że można je szybko połączyć ... jeśli przesuniesz cały zakres wartości do innego std::list
, cała operacja to O (1). Znacznie trudniej jest również unieważnić odniesienia do listy, co czasami może być ważne.
Generalnie wolę std::deque
to std::vector
robić, chyba że muszę mieć możliwość przekazania danych do biblioteki, która oczekuje surowej tablicy. std::vector
jest gwarantowana ciągłość, więc &v[0]
działa w tym celu. Nie pamiętam, kiedy ostatnio użyłem a std::list
, ale prawie na pewno dlatego, że potrzebowałem silniejszej gwarancji, że referencje pozostaną ważne.