HOWTO · C++
Deklarieren ein Array von Vektoren in C++ STL
In diesem Artikel wird erläutert, wie Sie ein Array von Vektoren in C++ deklarieren
Auf dieser Seite
Diese Anleitung zeigt, wie Sie in C++ entweder eine feste Anzahl von Vektoren oder einen dynamisch veränderbaren Vektor von Vektoren deklarieren. Der äußere Container bestimmt, wie viele Zeilen Sie hinzufügen können; jeder innere std::vector legt fest, wie viele Werte die jeweilige Zeile enthält. Wählen Sie die erste Form, wenn die Zeilenanzahl feststeht, und die zweite, wenn die äußere Sammlung wachsen oder schrumpfen können muss.
Zwischen einem festen Array und einem Vektor von Vektoren wählen
Ein Array von Vektoren hat eine zur Compilezeit festgelegte Zeilenanzahl, während jede Zeile weiterhin ein Vektor ist, der unabhängig wachsen kann. Auch die Zeilenanzahl eines Vektors von Vektoren lässt sich ändern; außerdem können seine Zeilen unterschiedlich lang sein. Ein Vektor von Vektoren ist daher nicht automatisch eine rechteckige Matrix. Er eignet sich beispielsweise für Adjazenzlisten, in denen jeder Eintrag eine andere Anzahl von Nachbarn haben kann.
Beide Formen speichern Vektoren als Elemente, sodass die inneren Vektoren ihren Speicher selbst verwalten. Keine der beiden Deklarationen garantiert, dass jede Zeile gleich viele Werte enthält. Wenn Ihr Algorithmus eine rechteckige Form voraussetzt, initialisieren Sie jede Zeile mit derselben Breite und erhalten Sie diese Eigenschaft bei Änderungen an den Daten.
Ein Array von Vektoren mit C-Array-Syntax deklarieren
Für eine feste Zeilenanzahl deklarieren Sie ein Array, dessen Elementtyp std::vector<int> ist, zum Beispiel std::vector<int> rows[3];. Das Array enthält drei Vektorelemente. Diese Vektoren sind zunächst leer, doch Sie können einer Zeile mit rows[0].push_back(10) Werte hinzufügen. Das Array selbst lässt sich nicht um einen vierten Vektor erweitern. Verwenden Sie einen dynamisch veränderbaren äußeren Container, wenn sich die Zeilenanzahl ändern muss.
Diese Syntax ist hilfreich, wenn die Zeilenanzahl zur festen Struktur des Programms gehört. Die Größe des Arrays wird durch seine Deklaration festgelegt, während sich die Größe jedes Vektors im Programm ändern kann. Für die beiden Dimensionen gelten somit unterschiedliche Regeln: Das äußere Array ist fest, die inneren Vektoren sind dynamisch veränderbar.
Einen dynamisch veränderbaren Vektor von Vektoren deklarieren
Verwenden Sie std::vector<std::vector<int>>, wenn sich die Zeilenanzahl ändern können soll. Mit einer Initialisierungsliste lassen sich Zeilen unterschiedlicher Anfangslänge erstellen. Alternativ erzeugt std::vector<std::vector<int>> rows(3, std::vector<int>(2, 0)); drei Zeilen mit jeweils zwei Nullen. Bei dieser Konstruktorform gibt das erste Argument die Zeilenanzahl an; das zweite ist ein Vektor, der als Vorlage für jede Zeile kopiert wird.
Mit rows.push_back({8, 9}) können Sie eine neue Zeile und mit rows[0].push_back(7) einen Wert zu einer vorhandenen Zeile hinzufügen. Wird eine Zeile vergrößert oder verkleinert, ändert sich die Größe der übrigen Zeilen nicht automatisch. Verwenden Sie den Konstruktor für ein regelmäßiges Ausgangsraster und eine Initialisierungsliste oder den zeilenweisen Aufbau, wenn die Zeilen unterschiedlich lang sein sollen.
Auf einen Vektor von Vektoren zugreifen und ihn durchlaufen
Verwenden Sie rows[row][column] für den direkten Zugriff, wenn Sie wissen, dass die Indizes gültig sind. Jeder Index wird auf einen anderen Vektor angewendet: Der erste wählt eine äußere Zeile aus, der zweite einen Wert innerhalb dieser Zeile. Da Zeilen unterschiedlich lang sein können, ist ein Spaltenindex, der für eine Zeile gültig ist, nicht unbedingt auch für eine andere gültig.
Verwenden Sie rows.at(row).at(column), wenn Sie einen zugriffsgeprüften Zugriff wünschen; at() meldet einen Zugriff außerhalb des gültigen Bereichs, statt unbemerkt hinter das Ende des ausgewählten Vektors zuzugreifen. Um alle Werte zu durchlaufen, ohne gleich lange Zeilen vorauszusetzen, verwenden Sie verschachtelte bereichsbasierte Schleifen. Binden Sie den inneren Wert per Referenz (int& value), wenn die Schleife gespeicherte Elemente ändern soll; für reine Lesezugriffe eignet sich eine Kopie oder eine konstante Referenz. Das vollständige Beispiel unten veranschaulicht beide Deklarationsformen, Indizierung, zugriffsgeprüften Zugriff, das Hinzufügen von Elementen und das Ändern von Werten per Referenz.
Dieses vollständige Programm zeigt beide Containerformen und greift auf ihre Werte zu:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <iostream>
#include <vector>
int main() {
std::vector<int> fixed_rows[3] = {{1, 2}, {3}, {4, 5, 6}};
std::vector<std::vector<int>> rows{{1, 2}, {3}, {4, 5, 6}};
fixed_rows[0].push_back(7);
rows.push_back({8, 9});
rows[1].push_back(7);
rows.at(0).at(1) = 20;
std::cout << fixed_rows[0][2] << '\n';
std::cout << rows.at(0).at(1) << '\n';
for (auto& row : rows) {
for (int& value : row) {
value *= 2;
std::cout << value << ' ';
}
std::cout << '\n';
}
}