HOWTO · C++
Wie man Vektor in Array in C++ konvertiert
Dieser Artikel führt ein, wie man einen Vektor in ein Array in C++ konvertiert
Auf dieser Seite
Ein std::vector speichert seine Elemente zusammenhängend im Speicher. Daher können APIs, die einen Zeiger und eine Elementanzahl entgegennehmen, direkt auf diesen Speicher zugreifen. Das ermöglicht einen Zugriff wie auf ein Array, erstellt aber kein separates Array: Der Zeiger verweist auf Elemente, die dem Vektor gehören. Benötigt der aufrufende Code unabhängigen Speicher, kopieren Sie die Elemente in ein ausreichend großes Ziel.
Verwenden Sie data() für eine temporäre Sicht über einen Zeiger, std::copy für eine unabhängige Kopie und std::transform, wenn sich die kopierten Werte ändern sollen. Der Vektor muss so lange bestehen bleiben, wie ein Zeiger auf seine Elemente verwendet wird. Operationen, die den Vektor neu allokieren, machen Zeiger auf seinen Speicher unbrauchbar.
Mit data() auf Vektorelemente wie auf ein Array zugreifen
Das Element data() gibt einen Zeiger auf den zusammenhängenden Speicherbereich der Vektorelemente zurück. Übergeben Sie ihn zusammen mit size() an eine API, die einen Zeiger und eine Elementanzahl erwartet. Der Zeiger verweist auf den Vektor: Schreibzugriffe über ihn verändern das entsprechende Vektorelement. Er darf weder länger als der Vektor noch nach einer Operation verwendet werden, die dessen Speicher neu allokiert.
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{1, 2, 3};
int* elements = values.data();
elements[1] = 20;
for (std::size_t i = 0; i < values.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << elements[i];
}
std::cout << '\n';
}
1 20 3
Bei einem Vektor, der leer sein kann, lässt sich data() aufrufen. Dereferenzieren Sie den zurückgegebenen Zeiger jedoch nur, wenn ein Element vorhanden ist. Verwenden Sie beim Indexzugriff über den Zeiger stets die Größe des Vektors als Grenze.
Den Adressoperator bei einem nicht leeren Vektor verwenden
Wenn sicher mindestens ein Element im Vektor enthalten ist, zeigt &values[0] auf das erste Element und kann für den Indexzugriff auf die Vektorelemente verwendet werden. Der Zeiger hat dieselben Besitz- und Lebensdauereigenschaften wie ein mit data() erhaltener Zeiger. Diese Voraussetzung ist wichtig: Bei einem leeren Vektor auf Element null zuzugreifen, ist ungültig. Verwenden Sie data(), wenn der Vektor leer sein könnte, und prüfen Sie weiterhin die Größe, bevor Sie den Zeiger dereferenzieren oder an Code übergeben, der mindestens ein Element voraussetzt.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{4, 5, 6};
int* elements = &values[0];
for (std::size_t i = 0; i < values.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << elements[i];
}
std::cout << '\n';
}
4 5 6
Vektorelemente mit std::copy() in ein Array kopieren
std::copy schreibt jedes Quellelement in einen bereits vorhandenen Zielbereich; es legt diesen Bereich nicht an. Ist die Elementanzahl zur Compilezeit bekannt, stellt std::array ein echtes Arrayobjekt fester Größe bereit. Größe und Elementtyp müssen für die Quelle ausreichen. Ist die Anzahl erst zur Laufzeit bekannt, verwenden Sie geeigneten dynamischen Speicher, etwa einen Ziel-std::vector oder ein eigenes dynamisches Array, falls die aufrufende API ausdrücklich eines verlangt.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <algorithm>
#include <array>
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{7, 8, 9};
std::array<int, 3> result{};
std::copy(values.begin(), values.end(), result.begin());
for (std::size_t i = 0; i < result.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << result[i];
}
std::cout << '\n';
}
7 8 9
Das Ziel ist unabhängig von der Quelle. Änderungen an result wirken sich daher nicht auf values aus. Stellen Sie vor dem Aufruf von std::copy sicher, dass im Ziel Platz für alle Quellelemente vorhanden ist; der Algorithmus prüft die Zielkapazität nicht. Ein eingebautes Array mit variabler Länge gehört nicht zum C++-Standard, da seine Länge eine Compilezeitkonstante sein muss.
Vektorelemente beim Kopieren mit std::transform() transformieren
Verwenden Sie std::transform, wenn beim Kopieren zugleich neue Werte berechnet werden sollen. Wie bei std::copy muss der Ausgabebereich Platz für ein Ergebnis je Eingabeelement bieten. Dieses Beispiel verdoppelt jede Ganzzahl und speichert sie in einem unabhängigen std::array.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <algorithm>
#include <array>
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{2, 3, 4};
std::array<int, 3> doubled{};
std::transform(values.begin(), values.end(), doubled.begin(),
[](int value) { return value * 2; });
for (std::size_t i = 0; i < doubled.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << doubled[i];
}
std::cout << '\n';
}
4 6 8
Für eine unveränderte Kopie drückt std::copy die Absicht direkter aus. Wählen Sie einen Zieltyp, der die transformierten Ergebnisse speichern kann, und bemessen Sie ihn für den gesamten Eingabebereich.
Vektorelemente mit einer for-Schleife kopieren
Eine Schleife bietet direkte Kontrolle über jede Zuweisung. Auch hier muss das Ziel groß genug sein: Jeder für die Quelle verwendete Index muss im Ziel gültig sein. Prüfen Sie bei einem Ziel fester Compilezeitgröße vor dem Kopieren, ob seine Ausdehnung der Vektorgröße entspricht. Bei einer erst zur Laufzeit bekannten Eingabe verwenden Sie ein passend dimensioniertes dynamisches Ziel.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <array>
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
std::vector<int> values{10, 11, 12};
std::array<int, 3> result{};
for (std::size_t i = 0; i < values.size(); ++i) {
result[i] = values[i];
}
for (std::size_t i = 0; i < result.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << result[i];
}
std::cout << '\n';
}
10 11 12
Wählen Sie data(), wenn eine API vorübergehend auf vektoreigene Elemente zugreifen soll, und sorgen Sie dafür, dass der Vektor währenddessen bestehen bleibt und gültig ist. Verwenden Sie std::copy, wenn ein separater Speicherbereich erforderlich ist, std::transform, wenn sich die Werte beim Kopieren ändern sollen, und eine Schleife, wenn eine elementweise Kontrolle hilfreich ist. Ein std::array fester Größe eignet sich bei einer zur Compilezeit bekannten Anzahl; andernfalls verwenden Sie, sofern die API es zulässt, ein Ziel mit Laufzeitgröße.