In welchem ​​Szenario verwende ich einen bestimmten STL-Container?

Lesezeit: 9 Minuten

In welchem ​​Szenario verwende ich einen bestimmten STL Container
Daniel Schluff

Ich habe mich in meinem Buch über C++ über STL-Container informiert, insbesondere im Abschnitt über die STL und ihre Container. Jetzt verstehe ich, dass jeder einzelne von ihnen seine eigenen spezifischen Eigenschaften hat, und ich bin kurz davor, sie alle auswendig zu lernen … Aber was ich noch nicht verstehe, ist, in welchem ​​​​Szenario jeder von ihnen verwendet wird.

Was ist die Erklärung? Beispielcode wird viel bevorzugt.

  • meinst du map, vectot, set etc?

    – Thomas Tempelmann

    23. Januar 2009 um 0:35 Uhr

  • Selbst wenn ich mir dieses Diagramm anschaue, kann ich nicht sagen, welches das beste für meine Frage wäre stackoverflow.com/questions/9329011/…

    – sergiol

    24. Februar 2012 um 19:32 Uhr

  • Ich habe eine erstellt Bearbeitbare Version von Mikaels C++ Container Cheat Sheet. Dies ist der Spickzettel von @MikaelPersson. Leider kann ich unter seiner Antwort keinen Kommentar abgeben, da ich noch keinen 50-Ruf habe.

    – Parker Schamblin

    14. August 2020 um 19:53 Uhr

1647190815 19 In welchem ​​Szenario verwende ich einen bestimmten STL Container
zdan

Dieser Spickzettel bietet eine ziemlich gute Zusammenfassung der verschiedenen Container.

Sehen Sie sich das Flussdiagramm unten als Leitfaden für die Verwendung in verschiedenen Nutzungsszenarien an:

http://linuxsoftware.co.nz/containerchoice.png

Erstellt von David Moore und lizensiert CC BY-SA 3.0

  • Dieses Flussdiagramm ist goldrichtig, ich wünschte, ich hätte so etwas in c#

    – Bruno

    1. Februar 2013 um 15:35 Uhr

  • Aktualisierter Link: C++-Container-Spickzettel.

    – Bill Door

    2. Januar 2014 um 22:56 Uhr

  • Ausgangspunkt muss sein vector eher dann leer. stackoverflow.com/questions/10699265/…

    – Äonil

    18. Februar 2014 um 19:34 Uhr


  • Sie haben jetzt unordered_map und unordered_set (und ihre Multi-Varianten), die nicht im Flussdiagramm enthalten sind, aber eine gute Wahl sind, wenn Sie sich nicht um die Reihenfolge kümmern, sondern Elemente nach Schlüssel finden müssen. Ihre Suche ist normalerweise O (1) anstelle von O (log n).

    – Aidiakapi

    12. Mai 2014 um 18:38 Uhr


  • @shuttle87 nicht nur diese Größe wird niemals variieren, sondern was noch wichtiger ist, diese Größe wird zur Kompilierzeit bestimmt und wird niemals variieren.

    – YoungJohn

    24. Juli 2015 um 20:51 Uhr


Hier ist ein Flussdiagramm, das von David Moores Version (siehe oben) inspiriert wurde, die ich erstellt habe und die (größtenteils) auf dem neuesten Stand des neuen Standards (C++11) ist. Dies ist nur meine persönliche Meinung dazu, es ist nicht unbestreitbar, aber ich dachte, es könnte für diese Diskussion wertvoll sein:

Geben Sie hier die Bildbeschreibung ein

  • Kannst du das Original zur Verfügung stellen? Es ist ein hervorragendes Diagramm. Vielleicht auf einem Blog oder GitHub bleiben?

    – Kevinarpe

    2. Mai 2015 um 13:28 Uhr

  • Dies ist ein hervorragendes Diagramm. Aber kann mir jemand erklären, was mit “beständigen Positionen” gemeint ist?

    – IDDQD

    26. April 2016 um 15:52 Uhr

  • @STALKER Persistente Positionen bedeutet, dass, wenn Sie einen Zeiger oder Iterator auf ein Element im Container haben, dieser Zeiger oder Iterator gültig bleibt (und auf dasselbe Element zeigt), unabhängig davon, was Sie dem Container hinzufügen oder daraus entfernen (solange es ist nicht das fragliche Element).

    – Michael Persson

    29. April 2016 um 4:22 Uhr

  • Dies ist wirklich ein großartiges Diagramm, aber ich denke vector (sorted) passt etwas nicht zum Rest. Es handelt sich nicht um eine andere Art von Container, sondern um die gleiche std::vector aber sortiert. Noch wichtiger ist, dass ich nicht verstehe, warum man a nicht verwenden könnte std::set für geordnete Iteration, wenn dies das Standardverhalten beim Iterieren durch eine Menge ist. Klar, wenn die Antwort vom geordneten Zugriff auf die Werte der Containermulde spricht []dann ok das geht nur mit einem soted std::vector. Aber in jedem Fall sollte die Entscheidung direkt nach der Frage „Bestellung erforderlich“ getroffen werden

    – RAs

    14. Oktober 2016 um 20:27 Uhr

  • @ user2019840 Ich wollte das Diagramm auf Standardcontainer beschränken. Was anstelle von “sortierter Vektor” erscheinen sollte, ist “flat_set” (von Boost.Container) oder Äquivalent (jede größere Bibliothek oder Codebasis hat ein flat_set-Äquivalent, AFAIK). Aber diese sind nicht standardmäßig und eine ziemlich eklatante Auslassung aus der STL. Und der Grund, warum Sie std::set oder std::map nicht (zumindest nicht häufig) durchlaufen möchten, ist, dass dies der Fall ist sehr ineffizient, dies zu tun.

    – Michael Persson

    27. November 2016 um 7:38 Uhr

1647190817 224 In welchem ​​Szenario verwende ich einen bestimmten STL Container
David Thornley

Einfache Antwort: verwenden std::vector für alles, es sei denn, Sie haben einen echten Grund, etwas anderes zu tun.

Wenn Sie einen Fall finden, bei dem Sie denken: “Mensch, std::vector funktioniert hier wegen X nicht gut”, gehen Sie von X aus.

  • Achten Sie jedoch darauf, beim Iterieren keine Elemente zu löschen / einzufügen. Verwenden Sie so weit wie möglich const_iterator, um dies zu vermeiden.

    – vrdhn

    20. März 2012 um 16:13 Uhr

  • Hmm … Ich denke, die Leute verwenden zu viel Vektor. Der Grund ist, dass der “funktioniert nicht”-Fall nicht so einfach passieren wird – also bleiben die Leute beim am häufigsten verwendeten Container und missbrauchen ihn zum Speichern von Listen, Warteschlangen, … Meiner Meinung nach – was dem Flussdiagramm entspricht – man sollte den Behälter basierend auf dem Verwendungszweck auswählen, anstatt das „Einer scheint für alle zu passen“ anzuwenden.

    – Schwarz

    13. April 2012 um 13:50 Uhr

  • @Black Point ist, Vektor ist normalerweise schneller, selbst bei Operationen, die theoretisch langsamer arbeiten sollten.

    – Bartek Banachewicz

    7. Februar 2013 um 0:30 Uhr

  • @Vardhan std::remove_if ist dem Ansatz “Löschen während der Iteration” fast immer überlegen.

    – fredoverflow

    29. April 2014 um 6:35 Uhr

  • Einige Benchmarks würden wirklich helfen, diese Diskussion weniger subjektiv zu führen.

    – Felix D.

    8. Dezember 2019 um 13:02 Uhr

Sehen Sie sich Effektive STL von Scott Meyers an. Es ist gut zu erklären, wie man die STL verwendet.

Wenn Sie eine bestimmte/unbestimmte Anzahl von Objekten speichern möchten und niemals eines löschen werden, dann ist ein Vektor genau das Richtige für Sie. Es ist der Standardersatz für ein C-Array und funktioniert wie eines, läuft aber nicht über. Sie können seine Größe auch vorher mit reserve() festlegen.

Wenn Sie eine unbestimmte Anzahl von Objekten speichern möchten, diese aber hinzufügen und löschen, möchten Sie wahrscheinlich eine Liste … weil Sie ein Element löschen können, ohne nachfolgende Elemente zu verschieben – im Gegensatz zu Vektoren. Es benötigt jedoch mehr Speicher als ein Vektor, und Sie können nicht sequentiell auf ein Element zugreifen.

Wenn Sie eine Reihe von Elementen nehmen und nur die eindeutigen Werte dieser Elemente finden möchten, können Sie sie alle in einen Satz einlesen und sie auch für Sie sortieren.

Wenn Sie viele Schlüssel-Wert-Paare haben und diese nach Schlüssel sortieren möchten, ist eine Zuordnung nützlich … aber sie enthält nur einen Wert pro Schlüssel. Wenn Sie mehr als einen Wert pro Schlüssel benötigen, können Sie einen Vektor/eine Liste als Wert in der Karte haben oder eine Multimap verwenden.

Es ist nicht in der STL, aber es ist im TR1-Update der STL: Wenn Sie viele Schlüssel-Wert-Paare haben, die Sie nach Schlüsseln suchen, und Sie sich nicht um ihre Reihenfolge kümmern, können Sie dies tun einen Hash verwenden möchten – das ist tr1::unordered_map. Ich habe es mit Visual C++ 7.1 verwendet, wo es stdext::hash_map hieß. Es hat eine Suche nach O (1) anstelle einer Suche nach O (log n) für map.

1647190817 855 In welchem ​​Szenario verwende ich einen bestimmten STL Container
Ebrahim

Ich habe das Flussdiagramm so umgestaltet, dass es 3 Eigenschaften hat:

  1. Ich denke, STL-Container sind in zwei Hauptklassen unterteilt. Die Basiscontainer und diese nutzen die Basiscontainer, um eine Richtlinie zu implementieren.
  2. Zunächst sollte das Flussdiagramm den Entscheidungsprozess in die Hauptsituationen unterteilen, über die wir entscheiden sollten, und dann jeden Fall näher erläutern.
  3. Bei einigen erweiterten Containern besteht die Möglichkeit, einen anderen Basiscontainer als Innencontainer zu wählen. Das Flussdiagramm sollte die Situationen berücksichtigen, in denen jeder der Basisbehälter verwendet werden kann.

Das Flussdiagramm: Geben Sie hier die Bildbeschreibung ein

Weitere Informationen finden Sie in dieser Link.

  • Hmmm, ich glaube deine std::array sollte sein std::unique_ptr<T[]>. Kurze Zusammenfassung: vector hat variable Größe, unique_ptr<T[]> hat die Größe zum Zeitpunkt der Erstellung bestimmt, array erfordert, dass seine Größe eine Kompilierzeitkonstante ist.

    – Ben Voigt

    14. August 2020 um 21:04 Uhr

1647190818 168 In welchem ​​Szenario verwende ich einen bestimmten STL Container
Peter Mortensen

Ein wichtiger Punkt, der bisher nur kurz erwähnt wurde, ist, dass Sie, wenn Sie zusammenhängenden Speicher benötigen (wie es ein C-Array gibt), nur verwenden können vector, arrayoder string.

Verwenden array wenn die Größe zur Kompilierzeit bekannt ist.

Verwenden string wenn Sie nur mit Zeichentypen arbeiten müssen und eine Zeichenfolge benötigen, nicht nur einen Allzweckcontainer.

Verwenden vector in allen anderen Fällen (vector sollte in den meisten Fällen ohnehin die Standardwahl für Container sein).

Mit allen dreien können Sie die verwenden data() Member-Funktion, um einen Zeiger auf das erste Element des Containers zu erhalten.

  • Hmmm, ich glaube deine std::array sollte sein std::unique_ptr<T[]>. Kurze Zusammenfassung: vector hat variable Größe, unique_ptr<T[]> hat die Größe zum Zeitpunkt der Erstellung bestimmt, array erfordert, dass seine Größe eine Kompilierzeitkonstante ist.

    – Ben Voigt

    14. August 2020 um 21:04 Uhr

In welchem ​​Szenario verwende ich einen bestimmten STL Container
Gebote

Es hängt alles davon ab, was Sie lagern möchten und was Sie mit dem Container machen möchten. Hier sind einige (sehr nicht erschöpfende) Beispiele für die Containerklassen, die ich am häufigsten verwende:

vector: Kompaktes Layout mit wenig oder keinem Speicheraufwand pro enthaltenem Objekt. Effizient zu iterieren. Anhängen, Einfügen und Löschen können teuer sein, insbesondere bei komplexen Objekten. Günstig ein enthaltenes Objekt per Index zu finden, zB myVector[10]. Verwenden Sie es dort, wo Sie in C ein Array verwendet hätten. Gut, wenn Sie viele einfache Objekte haben (z. B. int). Verwendung nicht vergessen reserve() bevor Sie dem Container viele Objekte hinzufügen.

list: Geringer Speicheraufwand pro enthaltenem Objekt. Effizient zu iterieren. Anhängen, Einfügen und Löschen sind billig. Verwenden Sie dort, wo Sie in C eine verkettete Liste verwendet hätten.

set (und multiset): Erheblicher Speicheraufwand pro enthaltenem Objekt. Verwenden Sie es dort, wo Sie schnell herausfinden müssen, ob dieser Container ein bestimmtes Objekt enthält, oder Container effizient zusammenführen.

map (und multimap): Erheblicher Speicheraufwand pro enthaltenem Objekt. Verwenden Sie, wo Sie Schlüssel-Wert-Paare speichern und Werte schnell nach Schlüssel suchen möchten.

Das Flussdiagramm auf der Spickzettel vorgeschlagen von zdan bietet eine umfassendere Anleitung.

  • “Kleiner Speicheraufwand pro enthaltenem Objekt” gilt nicht für die Liste. std::list ist als doppelt verkettete Liste implementiert und verwaltet daher 2 Zeiger pro gespeichertem Objekt, was nicht zu vernachlässigen ist.

    – Hanna Khalil

    16. November 2016 um 11:33 Uhr

  • Ich würde immer noch zwei Zeiger pro gespeichertem Objekt als “klein” zählen.

    – Gebote

    16. November 2016 um 16:18 Uhr

  • verglichen mit was? std::forward_list ist ein Container, der hauptsächlich vorgeschlagen wurde, um weniger Metadaten pro Objekt zu speichern (nur ein Zeiger). Während std::vector 0 Metadaten pro Objekt enthält. Also 2 Pointer ist im Vergleich zu anderen Containern nicht verhandelbar

    – Hanna Khalil

    17. November 2016 um 20:38 Uhr

  • Es hängt alles von der Größe Ihrer Objekte ab. Ich habe bereits gesagt, dass vector ein “kompaktes Layout mit wenig oder keinem Speicheraufwand pro enthaltenem Objekt” hat. Ich würde immer noch sagen, dass Liste im Vergleich zu Set und Map einen geringen Speicheraufwand und einen etwas größeren Speicheraufwand als Vektor hat. Ich bin mir nicht sicher, welchen Punkt Sie versuchen, TBH zu machen!

    – Gebote

    18. November 2016 um 12:44 Uhr


  • Alle modusbasierten Container haben in der Regel einen erheblichen Overhead aufgrund der dynamischen Zuweisung, die selten kostenlos ist. Es sei denn natürlich, Sie verwenden eine benutzerdefinierte Zuweisung.

    – MikeMB

    27. August 2017 um 5:52 Uhr

998460cookie-checkIn welchem ​​Szenario verwende ich einen bestimmten STL-Container?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy