Ponieważ istnieje mnóstwo odpowiedzi, możesz być zdezorientowany, ale podsumowując:
Użyj std::queue. Powód jest prosty: jest to struktura FIFO. Chcesz FIFO, używasz std::queue.
Sprawia, że twój zamiar staje się jasny dla innych, a nawet dla ciebie. A std::listalbo std::dequenie. Lista może wstawiać i usuwać w dowolnym miejscu, co nie jest tym, co ma robić struktura FIFO, a dequemoże dodawać i usuwać z dowolnego końca, czego również nie może zrobić struktura FIFO.
Dlatego powinieneś użyć queue.
Teraz zapytałeś o wydajność. Po pierwsze, zawsze pamiętaj o tej ważnej zasadzie: najpierw dobry kod, na końcu wydajność.
Powód jest prosty: ludzie, którzy dążą do wydajności przed czystością i elegancją, prawie zawsze kończą pracę na końcu. Ich kod staje się bzdurą, ponieważ porzucili wszystko, co dobre, aby naprawdę nic z tego nie wyciągnąć.
Pisząc najpierw dobry, czytelny kod, większość problemów z wydajnością rozwiąże się sama. A jeśli później stwierdzisz, że brakuje wydajności, możesz teraz łatwo dodać profiler do ładnego, czystego kodu i dowiedzieć się, gdzie jest problem.
To wszystko powiedział, std::queueto tylko adapter. Zapewnia bezpieczny interfejs, ale używa innego kontenera w środku. Możesz wybrać ten podstawowy kontener, a to zapewnia dużą elastyczność.
Więc jakiego podstawowego kontenera należy użyć? Wiemy, że std::listi std::dequeobaj zapewniają niezbędne funkcje ( push_back(), pop_front(), i front()), więc jak możemy zdecydować?
Po pierwsze, zrozum, że przydzielanie (i zwalnianie) pamięci nie jest na ogół szybkim zadaniem, ponieważ wymaga wyjścia do systemu operacyjnego i poproszenia go o zrobienie czegoś. A listmusi przydzielać pamięć za każdym razem, gdy coś jest dodawane i zwalniać ją, gdy zniknie.
Z dequedrugiej strony A przydziela porcje. Będzie przydzielać rzadziej niż plik list. Potraktuj to jako listę, ale każdy fragment pamięci może zawierać wiele węzłów. (Oczywiście sugerowałbym, aby naprawdę nauczyć się, jak to działa ).
Tak więc samo z tym dequepowinno działać lepiej, ponieważ nie radzi sobie tak często z pamięcią. W połączeniu z faktem, że obsługujesz dane o stałym rozmiarze, prawdopodobnie nie będzie trzeba ich przydzielać po pierwszym przejściu przez dane, podczas gdy lista będzie stale alokować i zwalniać.
Drugą rzeczą do zrozumienia jest wydajność pamięci podręcznej . Wychodzenie do pamięci RAM jest powolne, więc gdy procesor naprawdę tego potrzebuje, wykorzystuje ten czas najlepiej, zabierając z powrotem fragment pamięci do pamięci podręcznej. Ponieważ a dequealokuje w fragmentach pamięci, jest prawdopodobne, że dostęp do elementu w tym kontenerze spowoduje, że procesor CPU przywróci również resztę kontenera. Teraz dalszy dostęp do pliku dequebędzie szybki, ponieważ dane są w pamięci podręcznej.
W przeciwieństwie do listy, na której dane są przydzielane pojedynczo. Oznacza to, że dane mogą być rozproszone po całym miejscu w pamięci, a wydajność pamięci podręcznej będzie niska.
Biorąc to pod uwagę, a dequepowinno być lepszym wyborem. Dlatego jest to domyślny kontener podczas korzystania z pliku queue. To powiedziawszy, nadal jest to tylko (bardzo) wyedukowane przypuszczenie: będziesz musiał sprofilować ten kod, używając dequew jednym teście, a listw drugim, aby naprawdę wiedzieć na pewno.
Ale pamiętaj: spraw, aby kod działał z czystym interfejsem, a następnie martw się o wydajność.
Jan obawia się, że zawinięcie listlub dequespowoduje spadek wydajności. Po raz kolejny ani on, ani ja nie możemy powiedzieć na pewno bez profilowania go sami, ale są szanse, że kompilator będzie wbudowywał wywołania, które queuewykonuje. To znaczy, kiedy powiesz queue.push(), tak naprawdę powie queue.container.push_back(), całkowicie pomijając wywołanie funkcji.
Po raz kolejny jest to tylko zgadywanie, ale użycie a queuenie obniży wydajności w porównaniu z używaniem podstawowego kontenera surowego. Jak powiedziałem wcześniej, używaj queue, ponieważ jest czysty, łatwy w użyciu i bezpieczny, a jeśli to naprawdę staje się profilem problemu i testem.