std::vector versus std::array in C++

Lesezeit: 10 Minuten

stdvector versus stdarray in C
Zud

Was ist der Unterschied zwischen a std::vector und ein std::array in C++? Wann sollte man einem anderen den Vorzug geben? Was sind die Vor- und Nachteile der einzelnen? Alles, was mein Lehrbuch tut, ist aufzulisten, wie sie gleich sind.

  • Ich suche einen Vergleich z std::vector vs. std::array und wie sich die Begriffe unterscheiden.

    – Zud

    12. Dezember 2010 um 23:02 Uhr


  • Zud, std::array ist nicht dasselbe wie ein C++-Array. std::array ist ein sehr dünner Wrapper um C++-Arrays mit dem Hauptzweck, den Zeiger vor dem Benutzer der Klasse zu verbergen. Ich werde meine Antwort aktualisieren.

    – SchließungCowboy

    12. Dezember 2010 um 23:19 Uhr

  • Ich habe den Titel und den Text der Frage aktualisiert, um Ihre Klarstellung widerzuspiegeln.

    – Matteo Italien

    12. Dezember 2010 um 23:32 Uhr

  • Wenn Sie die Funktion constexpr oder consteval implementieren, können Sie std::array verwenden, aber nicht std::vector. stackoverflow.com/questions/33241909/…

    – Anton Krug

    10. April 2021 um 16:48 Uhr


stdvector versus stdarray in C
Matteo Italien

std::vector ist eine Vorlagenklasse, die ein dynamisches Array kapselt1, gespeichert im Heap, der automatisch wächst und schrumpft, wenn Elemente hinzugefügt oder entfernt werden. Es bietet alle Haken (begin(), end(), Iteratoren usw.), die dafür sorgen, dass es mit dem Rest der STL gut funktioniert. Es hat auch mehrere nützliche Methoden, mit denen Sie Operationen ausführen können, die auf einem normalen Array umständlich wären, wie zB das Einfügen von Elementen in der Mitte eines Vektors (es erledigt die ganze Arbeit des Verschiebens der folgenden Elemente im Hintergrund).

Da es die Elemente im auf dem Heap zugewiesenen Speicher speichert, hat es in Bezug auf statische Arrays einen gewissen Overhead.

std::array ist eine Vorlagenklasse, die ein Array mit statischer Größe kapselt, das im Objekt selbst gespeichert ist. Wenn Sie also die Klasse auf dem Stack instanziieren, befindet sich das Array selbst auf dem Stack. Seine Größe muss zur Kompilierzeit bekannt sein (sie wird als Vorlagenparameter übergeben) und kann nicht wachsen oder schrumpfen.

Es ist begrenzter als std::vector, aber es ist oft effizienter, besonders für kleine Größen, weil es in der Praxis meistens ein leichtgewichtiger Wrapper um ein Array im C-Stil ist. Es ist jedoch sicherer, da die implizite Konvertierung in einen Zeiger deaktiviert ist, und es bietet einen Großteil der STL-bezogenen Funktionalität von std::vector und der anderen Container, sodass Sie es problemlos mit STL-Algorithmen & Co. verwenden können. Wie auch immer, für die Beschränkung auf eine feste Größe ist es viel weniger flexibel als std::vector.

Zur Einführung in std::arrayschau mal Dieser Beitrag; zum schnellen Einstieg std::vector und zu den Operationen, die darauf möglich sind, möchten Sie vielleicht einen Blick darauf werfen Dokumentation.


  1. Tatsächlich denke ich, dass sie im Standard in Bezug auf die maximale Komplexität der verschiedenen Operationen beschrieben werden (z. B. wahlfreier Zugriff in konstanter Zeit, Iteration über alle Elemente in linearer Zeit, Hinzufügen und Entfernen von Elementen am Ende in konstanter amortisierter Zeit, usw.), aber AFAIK gibt es keine andere Methode, um solche Anforderungen zu erfüllen, als ein dynamisches Array zu verwenden. Wie von @Lucretiel angegeben, erfordert der Standard tatsächlich, dass die Elemente zusammenhängend gespeichert werden, also es ist ein dynamisches Array, das dort gespeichert wird, wo der zugeordnete Allokator es ablegt.

  • Zu Ihrer Fußnote: Der Standard garantiert zwar, dass die Zeigerarithmetik auf den internen Elementen funktioniert, was bedeutet, dass es sich um ein Array handeln muss: &vec[9] – &vec[3] == 6 ist wahr.

    – Lucretiel

    12. März 2012 um 6:17 Uhr


  • Ich bin mir ziemlich sicher, dass dieser Vektor nicht automatisch schrumpft, aber seit C ++ 11 können Sie Shrink_to_fit aufrufen.

    – Dino

    9. September 2014 um 9:24 Uhr

  • Ich bin total verwirrt von dem Begriff statisches Array und ich bin mir nicht sicher, was die richtige Terminologie ist. Sie meinen ein Array mit statischer Größe und kein statisches Variablen-Array (eines mit statischem Speicher). stackoverflow.com/questions/2672085/…. Was ist die richtige Terminologie? Ist statisches Array ein schlampiger Begriff für ein Array mit fester Größe?

    – Z-Boson

    21. Oktober 2014 um 11:30 Uhr


  • @Zboson: es geht definitiv nicht nur dir so, statisch ist ein ziemlich missbrauchter Begriff; genau dieses static Das Schlüsselwort in C++ hat drei verschiedene, voneinander unabhängige Bedeutungen, und der Begriff wird auch oft verwendet, um über Dinge zu sprechen, die zur Kompilierzeit behoben werden. Ich hoffe, dass “statische Größe” etwas klarer ist.

    – Matteo Italien

    21. Oktober 2014 um 12:55 Uhr

  • Eine Sache zu beachten: Für die Echtzeitprogrammierung (wo Sie nicht haben sollten irgendein dynamische Zuweisung/Aufhebung der Zuweisung nach dem Start) std::array wäre wahrscheinlich std::vector vorzuziehen.

    – TED

    13. Januar 2017 um 15:20 Uhr

1646632823 73 stdvector versus stdarray in C
Markus Lakata

Um einen Punkt von @MatteoItalia hervorzuheben: Der Effizienzunterschied besteht darin, wo die Daten gespeichert werden. Heap-Speicher (erforderlich bei vector) erfordert einen Aufruf an das System, um Speicher zuzuweisen, und dies kann teuer werden, wenn Sie Zyklen zählen. Stapelspeicher (möglich für array) ist praktisch “null Overhead” in Bezug auf die Zeit, da die Speicherzuweisung nur durch das Anpassen des Stapelzeigers erfolgt und dies nur einmal beim Aufrufen einer Funktion erfolgt. Der Stack vermeidet auch eine Speicherfragmentierung. Um sicher zu sein, std::array wird nicht immer auf dem Stack sein; Es hängt davon ab, wo Sie es zuweisen, aber es wird immer noch eine Speicherzuweisung weniger vom Heap im Vergleich zum Vektor erforderlich sein. Wenn Sie eine haben

  • kleines “Array” (sagen wir unter 100 Elementen) – (ein typischer Stack ist etwa 8 MB groß, weisen Sie dem Stack also nicht mehr als ein paar KB oder weniger zu, wenn Ihr Code rekursiv ist)
  • Die Größe wird festgelegt
  • Die Lebensdauer liegt im Funktionsbereich (oder ist ein Elementwert mit derselben Lebensdauer wie die übergeordnete Klasse).
  • Du zählst Zyklen,

Verwenden Sie auf jeden Fall a std::array über einen Vektor. Wenn eine dieser Anforderungen nicht zutrifft, verwenden Sie a std::vector.

  • Gute Antwort. “Sicher, std::array wird nicht immer auf dem Stack sein; es hängt davon ab, wo Sie es zuweisen.” Wie könnte ich also ein std::array erstellen, das sich nicht auf dem Stack mit einer großen Anzahl von Elementen befindet?

    – Trilarion

    18. Januar 2017 um 9:45 Uhr

  • @ Trilarion verwenden new std::array oder machen Sie es zu einem Mitglied einer Klasse, die Sie mit “new” zuweisen.

    – Mark Lakata

    18. Januar 2017 um 15:37 Uhr

  • Das bedeutet also new std::array Erwartet immer noch, seine Größe zur Kompilierzeit zu kennen und kann seine Größe nicht ändern, lebt aber immer noch auf dem Haufen?

    – Trilarion

    18. Januar 2017 um 16:12 Uhr

  • Jawohl. Es gibt keinen wesentlichen Vorteil bei der Verwendung new std::array vs new std::vector.

    – Mark Lakata

    18. Januar 2017 um 18:34 Uhr

1646632825 354 stdvector versus stdarray in C
SchließungCowboy

Verwendung der std::vector<T> Klasse:

  • …ist genauso schnell wie bei der Verwendung integrierter Arrays, vorausgesetzt, Sie tun nur die Dinge, die Sie mit integrierten Arrays tun können (Lesen und Schreiben in vorhandene Elemente).

  • …ändert automatisch die Größe, wenn neue Elemente eingefügt werden.

  • …ermöglicht das Einfügen neuer Elemente am Anfang oder mitten drin des Vektors, wodurch die restlichen Elemente automatisch “nach oben” “verschoben” werden (macht das Sinn?). Es erlaubt Ihnen, Elemente überall in der zu entfernen std::vectorwodurch die restlichen Elemente automatisch nach unten verschoben werden.

  • …ermöglicht es Ihnen, einen bereichsgeprüften Lesevorgang mit dem durchzuführen at() Methode (Sie können immer die Indexer verwenden [] wenn Sie diese Prüfung nicht wünschen).

Es gibt zwei drei Hauptvorbehalte zur Verwendung std::vector<T>:

  1. Sie haben keinen zuverlässigen Zugriff auf den zugrunde liegenden Zeiger, was dürfen ein Problem sein, wenn Sie es mit Funktionen von Drittanbietern zu tun haben, die die Adresse eines Arrays verlangen.

  2. Die std::vector<bool> Klasse ist dumm. Es ist als komprimiertes Bitfeld implementiert, nicht als Array. Vermeiden Sie es, wenn Sie ein Array von möchten boolS!

  3. Während der Nutzung, std::vector<T>s werden etwas größer sein als ein C++-Array mit der gleichen Anzahl von Elementen. Dies liegt daran, dass sie eine kleine Menge anderer Informationen im Auge behalten müssen, z. B. ihre aktuelle Größe und wann immer sie möchten std::vector<T>s Größe ändern, reservieren sie mehr Platz, als sie benötigen. Dies soll verhindern, dass sie jedes Mal die Größe ändern müssen, wenn ein neues Element eingefügt wird. Dieses Verhalten kann durch Bereitstellung einer benutzerdefinierten geändert werden allocatoraber ich hatte nie das Bedürfnis, das zu tun!


Bearbeiten: Nachdem ich Zuds Antwort auf die Frage gelesen hatte, hatte ich das Gefühl, ich sollte Folgendes hinzufügen:

Die std::array<T> class ist nicht dasselbe wie ein C++-Array. std::array<T> ist ein sehr dünner Wrapper um C++-Arrays mit dem Hauptzweck, den Zeiger vor dem Benutzer der Klasse zu verbergen (in C++ werden Arrays implizit als Zeiger umgewandelt, oft mit erschreckender Wirkung). Die std::array<T> Klasse speichert auch ihre Größe (Länge), was sehr nützlich sein kann.

  • Es ist “genauso schnell” wie die Verwendung eines dynamisch zugewiesenen integrierten Arrays. Andererseits kann die Verwendung eines automatischen Arrays eine erheblich unterschiedliche Leistung haben (und nicht nur während der Zuweisung aufgrund von Lokalitätseffekten).

    – Ben Voigt

    27. August 2013 um 18:13 Uhr

  • Für Nicht-Bool-Vektoren in C++11 und höher können Sie aufrufen data() auf einen std::vector<T> um den zugrunde liegenden Zeiger zu erhalten. Sie können auch einfach die Adresse von Element 0 nehmen (funktioniert garantiert mit C++11, wird wahrscheinlich mit früheren Versionen funktionieren).

    – Matt

    25. Juni 2015 um 18:01 Uhr


  • Im letzten Absatz meinst du C-Array? Rechts ?

    – Tanishq-Banyal

    18. Juni 2021 um 8:53 Uhr

Wenn Sie mehrdimensionale Arrays verwenden möchten, gibt es einen zusätzlichen Unterschied zwischen std::array und std::vector. Bei einem mehrdimensionalen std::array werden die Elemente in allen Dimensionen im Speicher gepackt, genau wie bei einem Array im ac-Stil. Ein multidimensionaler std::vector wird nicht in alle Dimensionen gepackt.

Angesichts der folgenden Erklärungen:

int cConc[3][5];
std::array<std::array<int, 5>, 3> aConc;
int **ptrConc;      // initialized to [3][5] via new and destructed via delete
std::vector<std::vector<int>> vConc;    // initialized to [3][5]

Ein Zeiger auf das erste Element im Array im c-Stil (cConc) oder im std::array (aConc) kann durch das gesamte Array iteriert werden, indem jedem vorangehenden Element eine 1 hinzugefügt wird. Sie sind dicht gepackt.

Ein Zeiger auf das erste Element im Vektorarray (vConc) oder im Zeigerarray (ptrConc) kann nur durch die ersten 5 (in diesem Fall) Elemente iteriert werden, und dann gibt es 12 Bytes (auf meinem System) Overhead für die nächster Vektor.

Dies bedeutet, dass ein std::vector> Array als initialisiert wird [3][1000] Das Array wird im Speicher viel kleiner sein als eines, das als a initialisiert wird [1000][3] array, und beide haben einen größeren Arbeitsspeicher als ein std:array, das so oder so zugewiesen wurde.

Das bedeutet auch, dass Sie nicht einfach ein mehrdimensionales Vektor- (oder Zeiger-) Array an OpenGL übergeben können, ohne den Speicheraufwand zu berücksichtigen, aber Sie können naiv ein mehrdimensionales std::array an OpenGL übergeben und es funktioniert.

Fassen Sie die obige Diskussion in einer Tabelle zum schnellen Nachschlagen zusammen:

Array im C-Stil std::array std::Vektor
Größe Fest/Statisch Fest/Statisch Dynamisch
Speichereffizienz Effizienter Effizienter Weniger effizient
(Kann seine Größe bei einer neuen Zuweisung verdoppeln.)
Kopieren Über Elemente iterieren
oder std::copy() verwenden
Direkte Kopie: a2 = a1; Direktkopie: v2 = v1;
Übergang zur Funktion Zeiger übergeben.
(Größe nicht in Funktion verfügbar)
Wert übergeben Wert übergeben
(Größe in dieser Funktion verfügbar)
Größe Größe von (a1) / Größe von (a1[0]) a1.Größe() v1.size()
Anwendungsfall Für schnellen Zugriff und wann
Einfügungen/Löschungen werden nicht häufig benötigt.
Gleich wie klassisches Array, aber
sicherer und einfacher zu übergeben und zu kopieren.
Bei häufigen Ergänzungen bzw
Löschungen könnten erforderlich sein

  • void foo(T (& arr)[N]) würde die Array-Größe erfassen. ähnliche Magic-Arguments-in-Function-Templates

    – I.Omar

    14. November 2021 um 18:22 Uhr

  • Ich würde diese Zeilen hinzufügen: “| Wertesemantik | nein | ja | ja |” und “| Move | O(N) | O(N) | O(1) |” und “| Vertausche | O(N) | O(N) | O(1) |”

    – alfC

    1. Februar um 19:11 Uhr

1646632827 226 stdvector versus stdarray in C
Saif al-Harthi

Ein Vektor ist eine Containerklasse, während ein Array ein zugewiesener Speicher ist.

  • void foo(T (& arr)[N]) würde die Array-Größe erfassen. ähnliche Magic-Arguments-in-Function-Templates

    – I.Omar

    14. November 2021 um 18:22 Uhr

  • Ich würde diese Zeilen hinzufügen: “| Wertesemantik | nein | ja | ja |” und “| Move | O(N) | O(N) | O(1) |” und “| Vertausche | O(N) | O(N) | O(1) |”

    – alfC

    1. Februar um 19:11 Uhr

963390cookie-checkstd::vector versus std::array in C++

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

Privacy policy