Wie kann ich effizient wählen Sie eine Standard-Bibliothek container in C++11?
Es gibt ein bekanntes Bild (cheat sheet) namens "C++ Container-Wahl". Es ist ein Fluss-Diagramm, wählen Sie die beste container für die gewünschte Nutzung.
Weiß jemand, ob es bereits ein C++11-version?
Dies ist die Vorherige:
Noch nie gesehen vorher. danke!
Es ist bereits ein Teil der C++-Faq hier SO.
C++11 nur eingeführt, eine neue wahre container-Typ: der unordered_X Container. Sie würde Sie nur Durcheinander die Tabelle deutlich, da gibt es eine Reihe von überlegungen bei der Entscheidung, ob eine hash-Tabelle ist, geeignet.
James hat Recht, es gibt noch mehr Fälle, in Vektor-als das, was die Tabelle zeigt. Der Vorteil der Daten-Lokalität übertrifft in vielen Fällen die mangelnde Effizienz in einigen Operationen (bald mehr C++11). Ich finde nicht, e Karte, so nützlich auch für c++03
Das ist nett, aber ich denke, das Lesen jedem gängigen lehrbuch der Datenstrukturen lassen Sie sich in einem Zustand, wobei Sie nicht nur neu erfinden, dieses Flussdiagramm in ein paar Minuten, aber wissen auch eine Menge nützlicher Sachen, die in diesem Flussdiagramm beschönigt.
Es ist bereits ein Teil der C++-Faq hier SO.
C++11 nur eingeführt, eine neue wahre container-Typ: der unordered_X Container. Sie würde Sie nur Durcheinander die Tabelle deutlich, da gibt es eine Reihe von überlegungen bei der Entscheidung, ob eine hash-Tabelle ist, geeignet.
James hat Recht, es gibt noch mehr Fälle, in Vektor-als das, was die Tabelle zeigt. Der Vorteil der Daten-Lokalität übertrifft in vielen Fällen die mangelnde Effizienz in einigen Operationen (bald mehr C++11). Ich finde nicht, e Karte, so nützlich auch für c++03
Das ist nett, aber ich denke, das Lesen jedem gängigen lehrbuch der Datenstrukturen lassen Sie sich in einem Zustand, wobei Sie nicht nur neu erfinden, dieses Flussdiagramm in ein paar Minuten, aber wissen auch eine Menge nützlicher Sachen, die in diesem Flussdiagramm beschönigt.
InformationsquelleAutor BlakBat | 2012-05-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht, dass ich wüsste, aber es kann getan werden, textlich denke ich. Auch die Karte ist etwas abseits, weil
list
ist nicht so eine gute container im Allgemeinen, und weder istforward_list
. Beide Listen sind sehr spezialisierte Behälter für Nischen-Anwendungen.So bauen Sie ein Diagramm, brauchen Sie nur zwei einfache guidelines:
Sich Gedanken über die Leistung in der Regel nutzlos auf den ersten. Der big O überlegungen eigentlich nur kick-in, wenn Sie beginnen Umgang mit ein paar tausend (oder mehr) Elemente.
Gibt es zwei große Kategorien von Containern:
find
Betriebund dann können Sie bauen mehrere Adapter auf der Oberseite von Ihnen:
stack
,queue
,priority_queue
. Verlasse ich den Adapter hier, Sie sind ausreichend spezialisierte erkennbar sein.Frage 1: Assoziative ?
Frage 1.1: Bestellt ?
unordered_
container zu verwenden, ansonsten seine traditionelle bestellt Gegenstück.Frage 1.2: Separate Taste ?
map
verwenden, ansonsten einset
Frage 1.3: Duplikate ?
multi
, sonst nicht.Beispiel:
Angenommen, ich habe mehrere Personen mit einer eindeutigen ID zu Ihnen, und ich würde gerne rufen Sie eine person, die Daten aus dem ID so einfach wie möglich.
Möchte ich ein
find
- Funktion, damit eine assoziative container1.1. Ich konnte nicht weniger kümmern, um somit ein
unordered_
container1.2. Mein key (ID) getrennt von dem Wert zugeordnet ist, also eine
map
1.3. Die ID eindeutig ist, damit keine doppelten sollte kriechen.
Die endgültige Antwort ist:
std::unordered_map<ID, PersonData>
.Frage 2: Speicher stabil ?
list
Frage 2.1: Die ?
list
; einforward_list
ist nur nützlich für geringeren Speicherbedarf.Frage 3: Dynamisch Größe ?
{ ... }
syntax), dann verwenden Sie einarray
. Es ersetzt das traditionelle C-array, aber mit praktischen Funktionen.Frage 4: Double-ended ?
deque
verwenden, ansonsten einvector
.Beachten Sie, dass standardmäßig, es sei denn, Sie brauchen einen assoziativen container, Ihre Wahl wird eine
vector
. Es stellt sich heraus, es ist auch Sutter und Stroustrup ' s Empfehlung.array
nicht erforderlich, einen Standard-baubar Art; 2) Auswahl desmulti
s nicht so sehr um die Duplikate erlaubt, sondern mehr darüber, ob halten Sie Fragen (Sie können die Duplikate in nicht-multi
Container, es passiert einfach, dass nur einer wird gehalten).Das Beispiel ist ein bisschen off. 1) wir können "finden" (nicht die member-Funktion, die "<Algorithmus>") auf eine nicht assoziative container, 1.1) wenn wir brauchen, um herauszufinden, "effizient", und unordered_ werden O(1) und nicht O(log n).
ist viel schmackhafter als
std::find(map.begin(), map.end(), [&](decltype(map.front()) p) { return p.first < key; }));
obwohl, deshalb ist es wichtig, semantisch, dassfind
ist eine member-Funktion eher als die, die aus<algorithm>
. Wie für die O(1) vs O(log n), es hat keinen Einfluss auf die Semantik; ich werde entfernen Sie die "effizient" aus dem Beispiel, und ersetzen Sie es mit "leicht".Ich habe wirklich daran gewöhnen, dass die lambda-syntax...
Danke, editiert.
InformationsquelleAutor Matthieu M.
Ich wie Matthieu Antwort, aber ich werde noch einmal der Ablaufplan:
, Wenn NICHT für die Verwendung der std::vector
Standardmäßig, wenn Sie einen container von Sachen, verwenden Sie
std::vector
. So, alle anderen container ist nur dann gerechtfertigt, indem Sie einige Funktionen, die alternative zustd::vector
.Konstruktoren
std::vector
verlangt, dass seine Inhalte bewegen-baubar, da es braucht, um in der Lage, schieben Sie die Gegenstände um. Dies ist nicht eine schreckliche Bürde, die auf den Inhalt (beachten Sie, dass die default-Konstruktoren sind nicht erforderlich, Dankemplace
und so weiter). Jedoch, die meisten anderen Behälter benötigen keine besonderen Konstruktor (wieder, Dankemplace
). Also, wenn Sie ein Objekt haben, wo Sie absolut nicht Umsetzung einer move-Konstruktor, dann müssen Sie wählen Sie etwas anderes.Einen
std::deque
wäre der Allgemeine Ersatz -, dass viele der Eigenschaften desstd::vector
, aber Sie können nur stecken Sie an beiden enden der deque. Fügt in der Mitte erfordern verschieben. Einstd::list
Orten keine Anforderung auf Ihren Inhalt.Muss Bools
std::vector<bool>
ist... nicht. Gut, es ist standard. Aber es ist nicht einevector
im üblichen Sinne, wie Operationen, diestd::vector
normal erlaubt sind, sind verboten. Und das wird es ganz sicher nicht enthaltenbool
s.Deshalb, wenn Sie brauchen echte
vector
Verhalten aus einem container vonbool
s, du bist nicht gehen, um es vonstd::vector<bool>
. So müssen Sie dies mit einemstd::deque<bool>
.Suchen
Wenn Sie brauchen, um die Elemente in einem container, und die Suche tag kann man nicht einfach einen index, dann müssen Sie möglicherweise aufgeben
std::vector
zu Gunsten vonset
undmap
. Beachten Sie das wichtige Wort "kann"; a sortiertstd::vector
ist manchmal eine sinnvolle alternative. Oder "Boost".Containerflat_set/map
, die Implementierung einer sortiertenstd::vector
.Gibt es nun vier Varianten dieser, jede mit Ihren eigenen Bedürfnissen.
map
wenn der such-tag ist nicht das gleiche wie das Element, das Sie suchen für sich selbst. Sonst einset
.unordered
wenn Sie eine viel der Elemente im container und Suche Leistung absolut sein mussO(1)
eher alsO(logn)
.multi
wenn Sie mehrere Punkte haben, um die gleiche Suche-tag.Bestellung
Wenn Sie einen container der die Elemente immer sortiert werden basierend auf einer bestimmten Vergleich Betrieb, können Sie ein
set
. Oder einmulti_set
wenn Sie mehrere Elemente den gleichen Wert haben.Oder Sie können eine sortierte
std::vector
, aber Sie haben, um es zu halten sortiert.Stabilität
Wenn Iteratoren und Referenzen werden ungültig ist manchmal ein Anliegen. Wenn Sie eine Liste der Elemente, so, dass Sie über Iteratoren/Zeiger auf diese Objekte in verschiedene andere Plätze, dann
std::vector
's Ansatz zur Ungültigkeitserklärung möglicherweise nicht geeignet. Jede Einfüge-operation kann die Ursache Abwertung, abhängig von der aktuellen Größe und Kapazität.std::list
bietet eine Feste Garantie: ein iterator und Ihre zugehörigen Referenzen/Zeiger sind nur dann ungültig, wenn das Objekt selbst aus dem container entfernt wird.std::forward_list
ist es, wenn der Speicher ist ein ernstes Problem.Wenn das zu starke Garantie
std::deque
bietet eine schwächere, aber nützliche Garantie. Aufhebungs-Ergebnisse von Insertionen in der Mitte, aber die Einfügungen in den Kopf oder Schwanz Ursachen nur die Ungültigkeitserklärung von Iteratoren, keine Zeiger/Referenzen auf die Elemente im container.Einlegen Leistung
std::vector
nur bietet Billig einfügen am Ende (und selbst dann wird es teuer, wenn Sie Schlag Kapazität).std::list
ist teuer in Bezug auf Leistung (jedes neu eingefügte Element kostet ein memory allocation), aber es ist konsistente. Es bietet auch die gelegentlich unverzichtbare Fähigkeit, shuffle-Elemente, um für praktisch keine Leistung Kosten, sowie das handeln mit items mit anderenstd::list
Behältern des gleichen Typs ohne performance-Verlust. Wenn Sie brauchen, um zu schieben das Zeug herum viel, verwenden Siestd::list
.std::deque
bietet eine Konstante-Zeit einfügen/entfernen am Kopf und Schwanz, aber die Einfügung in der Mitte ziemlich teuer werden kann. Also, wenn Sie brauchen, um hinzuzufügen/entfernen Sie Dinge aus der Vorder-sowie der Rückseite,std::deque
könnte das sein, was Sie brauchen.Es sollte angemerkt werden, dass, Dank move-Semantik
std::vector
insertion kann die Leistung nicht so schlecht, wie es verwendet werden. Einige Implementierungen implementiert eine form des move-Semantik-basierten Element kopieren (die so genannte "swaptimization"), aber jetzt, dass der Umzug ist Teil der Sprache, es ist Auftrag des standard.Keine Dynamischen Zuweisungen
std::array
ist ein feiner Behälter, wenn Sie wollen, dass die wenigsten möglich dynamische Zuordnungen. Es ist nur ein wrapper um ein C-array; dies bedeutet, dass Ihre Größe bekannt sein muss, an compile-Zeit. Wenn Sie damit Leben kann, dann verwenden Siestd::array
.Dass gesagt wird, mit
std::vector
undreserve
ing eine Größe würde genauso gut funktionieren, für ein eingegrenztesstd::vector
. Auf diese Weise, die tatsächliche Größe kann variieren, und Sie bekommen nur eine Speicherreservierung (es sei denn, Sie sprengen die Kapazität).std::sort
gibt es auchstd::inplace_merge
interessant, leicht zu platzieren, neue Elemente (nicht alsstd::lower_bound
+std::vector::insert
nennen). Schön zu erfahrenflat_set
undflat_map
!Sie können auch nicht verwenden Sie einen Vektor mit 16-byte-ausgerichtet-Typen. Auch ein guter Ersatz für
vector<bool>
istvector<char>
.auch nicht verwenden Sie einen Vektor mit 16-byte-ausgerichtet-Typen." Wer sagt das? Wenn
std::allocator<T>
nicht unterstützen, dass die Ausrichtung (und ich weiß nicht, warum wäre es nicht), dann kann man immer verwenden Sie Ihre eigenen benutzerdefinierten Zuweisung.C++11 ist
std::vector::resize
hat eine überladung, die hat keinen Wert (es dauert nur die neue Größe; neue Elemente werden default-konstruiert in-place). Auch, warum sind die Compiler nicht in der Lage richtig auszurichten Wert-Parameter, auch wenn Sie erklärt haben, dass die Ausrichtung?bitset
für bool wenn Sie wissen, die Größe im Voraus en.cppreference.com/w/cpp/utility/bitsetInformationsquelleAutor Nicol Bolas
Hier ist der C++11-version der obigen Flussdiagramm. [Zitat ohne Namensnennung in seinen ursprünglichen Autor, Mikael Persson]
Wow, ich bin froh, dass irgendjemand die Mühe gemacht zu zitieren, eine Quelle.
InformationsquelleAutor Wasim Thabraze
Hier ist eine schnelle Drehung, obwohl es muss wahrscheinlich arbeiten
Können Sie feststellen, dass dies unterscheidet sich Wild aus C++03-version, vor allem aufgrund der Tatsache, dass ich weiß wirklich nicht, wie verknüpften Knoten. Die verlinkten Knoten-Container können in der Regel schlagen in der Leistung durch eine nicht verlinkte container, außer in ein paar seltenen Fällen. Wenn Sie nicht wissen, was diese Situationen sind, und haben Zugang zu steigern, nicht verknüpfte Knoten-Container. (std::list, std::slist, std::map, std::multimap, std::set, std::multiset). Diese Liste konzentriert sich hauptsächlich auf kleine und mittlere sided-Container, weil (A) das ist zu 99,99% von dem, was wir im code, und (B) Große Anzahl von Elementen benötigen, benutzerdefinierte algorithmen, nicht in verschiedene Behälter.
InformationsquelleAutor Mooing Duck