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.
std::deque
przeciwstd::vector
? Będziesz zaskoczony ...Rzeczy się zmieniły
Jesteśmy teraz w Qt 5.8 i wiele się zmieniło, więc dokumentacja. Daje jasną i inną odpowiedź na to pytanie:
źródło
W
QVector
jest podobny dostd::vector
.QLinkedList
jest podobny dostd::list
.QList
jest wektorem indeksowanym, ale pozycja pamięci nie jest gwarantowana (podobnie jakstd::deque
).źródło
Z dokumentu QtList:
QList do użycia w większości przypadków. W przypadku struktur z tysiącem elementów umożliwia wydajne wstawianie w środku i zapewnia indeksowany dostęp.
prepend()
iappend()
bardzo szybko, ponieważ pamięć jest wstępnie alokowana na obu końcach wewnętrznej tablicy.QList<T>
jest tablicą wskaźników typu T. Jeśli T ma wskaźnik lub Qt współdzielony typ wskaźnika, obiekt jest przechowywany bezpośrednio w tablicyQVector
być preferowanym w przypadku wieluappend()
lubinsert()
nowych elementów o rozmiarze większym niż wskaźnik, ponieważQVector
przydziela pamięć dla swoich elementów w jednej alokacji sterty. W przypadkuQList
wstawienia lub dołączenia nowego elementu wymaga alokacji pamięci nowego elementu na stercie. Krótko mówiąc, jeśli chcesz, aby elementy zajmowały sąsiednie pozycje w pamięci lub jeśli Twoje elementy są większe niż wskaźnik i chcesz uniknąć narzutu związanego z przydzielaniem ich pojedynczo na stercie w czasie wstawiania, użyjQVector
.źródło
QVector
jest jak tablica, która może zmieniać rozmiar (zwiększać lub zmniejszać), ale wiąże się z dużymi transakcjami, obliczeniami i czasem.Na przykład, jeśli chcesz dodać element, tworzona jest nowa tablica, wszystkie elementy są kopiowane do nowej tablicy, nowy element jest dodawany na końcu, a stara tablica jest usuwana. I odwrotnie, aby również usunąć.
Jednak
QLinkedList
działa ze wskaźnikami. Tak więc, kiedy tworzony jest nowy element, przydzielana jest tylko nowa przestrzeń pamięci i jest ona łączona z jedynym fragmentem pamięci. Ponieważ działa ze wskaźnikami, jest szybszy i wydajny.Jeśli masz listę elementów, których nie spodziewasz się zmienić rozmiaru,
QVector
prawdopodobnie jest dobra, ale zwykleQLinkedList
jest używana do większości celów.źródło