Vektor Vector Initialisierung
-
29-09-2019 - |
Frage
Ich habe eine harte Zeit immer mein Kopf gewickelt, wie ein Vektor von Vektoren zu initialisieren.
typedef vector
Ich möchte dies entsprechen
level_1 (2 elements/vectors)
level_2 (7 elements/vectors)
level_3 (480 elements/vectors)
level_4 (31 elements of float)
die Elemente Adressierung ist nicht das Problem. Das sollte wie so einfach, wie etwas sein
dc[0][1][2][3];
Das Problem ist, dass ich es füllen muß mit Daten in aus, um aus einer Datei kommen, so dass aufeinanderfolgende Elemente müssen wie etwas platziert wird
dc[0][3][230][22];
dc[1][3][110][6]; //...etc
Also brauche ich die V von V initialisieren vorher.
Am ich mich oder ist dies so einfach wie
psychingfor 0..1
for 0..6
for 0..479
for 0..30
dc[i][j][k][l] = 0.0;
Es scheint nicht, wie das funktionieren soll. Irgendwie sind die Top-Level-Vektoren zunächst initialisiert werden muss.
Jede Hilfe sehr geschätzt. Ich bin sicher, dass dies muss einfacher sein, als ich es mir vor.
Lösung
-
Bitte Verwenden Sie keine verschachtelten Vektoren , wenn die Größe Ihrer Speicher bekannt ist, vor der Zeit , dh es gibt ein bestimmten Grund warum zB der erste Index muss der Größe 6, und wird sich nie ändern. verwendet nur eine einfache Anordnung. Noch besser wäre es, die Verwendung
boost::array
. Auf diese Weise erhalten Sie alle Vorteile eines einfachen Anordnung mit (speichern riesige Mengen an Speicherplatz, wenn Sie mehrdimensionale gehen), und die Vorteile eines echten Objektinstanziierung mit. -
Bitte Verwenden Sie keine verschachtelten Vektoren , wenn Ihr Speicher muss rechteckigem , dh Sie können eine Größe oder mehrere der Dimensionen, aber jede „Reihe“ Muss sein die gleiche Länge an einem gewissen Punkt. Verwenden
boost::multi_array
. Auf diese Weise dokumentieren Sie „dieser Speicher ist rechteckig“, speichert große Mengen an Speicherplatz und immer noch die Fähigkeit erhalten, um die Größe, Vorteile ein reales Objekt mit, etc.
Die Sache std::vector
ist, dass es (a) bedeutet, veränderbar und (b) sein muss über seinen Inhalt nicht im Geringsten kümmern, solange sie vom richtigen Typ sind. Dies bedeutet, dass, wenn Sie einen vector<vector<int> >
haben, dann alle „Zeilenvektoren“ jeweils eine eigene Buchführung Informationen pflegen müssen, wie lange sie sind - auch wenn Sie erzwingen möchten, dass sie alle die gleiche Länge sind. Es bedeutet auch, dass sie alle separate Speicherzuordnungen verwalten, das die Leistung (Cache-Verhalten) verletzt, und Abfälle noch mehr Platz, weil, wie std::vector
neu verteilt. boost::multi_array
ist mit der Erwartung konzipiert, dass Sie es, um die Größe möchten, wird aber nicht ständig es (für einen 2-dimensionalen Array / faces Reihen, für eine 3-dimensionale Array / etc.) durch Anhängen von Elementen Ändern der Größe werden bis zum Ende . std::vector
wird (potentiell) Abfall Raum entworfen, um sicherzustellen, dass der Betrieb nicht langsam ist. boost::multi_array
ist so konzipiert, um Platz zu sparen und hält alles ordentlich im Speicher organisiert.
Das heißt :
Ja, Sie brauchen etwas zu tun, bevor Sie Index in den Vektor. std::vector
wird nicht auf magische Weise bewirken, dass die Indizes in der Existenz Pop, weil Sie speichern dort etwas wollen. Dies ist jedoch leicht zu behandeln:
Sie können den Vektor mit der entsprechenden Menge von Nullen Standard initialisieren zuerst, und dann ersetzen, indem Sie den (size_t n, const T& value = T())
Konstruktor. Das heißt,
std::vector<int> foo(10); // makes a vector of 10 ints, each of which is 0
, weil ein "default-konstruiert" int den Wert 0 hat.
In Ihrem Fall müssen wir die Größe jeder Dimension angeben, durch Untervektoren zu schaffen, die in der entsprechenden Größe und lassen den Konstruktor sie kopieren. Das sieht aus wie:
typedef vector<float> d1;
typedef vector<d1> d2;
typedef vector<d2> d3;
typedef vector<d3> d4;
d4 result(2, d3(7, d2(480, d1(31))));
Das heißt, eine unbenannte d1
der Größe 31 aufgebaut ist, die verwendet wird, um den Standard d2
zu initialisieren, die verwendet wird, um den Standard d3
zu initialisieren, die verwendet wird, result
zu initialisieren.
Es gibt auch andere Ansätze, aber sie sind viel schwerfälliger, wenn Sie nur ein paar Nullen beginnen soll. Wenn Sie vorhaben, den gesamten Datensatz aus einer Datei zu lesen, aber:
-
Sie können
.push_back()
zu append auf einen Vektor verwenden. Machen Sie eine leered1
kurz vor der am weitesten innen Schleife, in denen sie immer wieder.push_back()
es zu füllen. Kurz nach der Schleife.push_back()
Sie das Ergebnis auf dend2
, die Sie kurz vor der nächsten innersten Schleife erstellt, und so weiter. -
Sie können einen Vektor der Größe vorher mit
.resize()
und dann Index in sie normalerweise (bis zu dem Betrag, dass Sie die Größe zu verändern).
Andere Tipps
Sie würden wahrscheinlich eine Größe oder Reservespeicher setzen müssen
Könnte Sie eine for-each oder eine für das verschachtelte nennen würde
myVector.resize(x); //or size
auf jeder Ebene.
EDIT: Ich gebe zu diesem Code nicht elegant ist. Ich mag @Karl Antwort, die der richtige Weg zu gehen.
Dieser Code wird erstellt und getestet. Es gedruckt 208320 Nullen der erwartet wird, (2 * 7 * 480 * 31)
#include <iostream>
#include <vector>
using namespace std;
typedef vector< vector < vector < vector< float > > > > DataContainer;
int main()
{
const int LEVEL1_SIZE = 2;
const int LEVEL2_SIZE = 7;
const int LEVEL3_SIZE = 480;
const int LEVEL4_SIZE = 31;
DataContainer dc;
dc.resize(LEVEL1_SIZE);
for (int i = 0; i < LEVEL1_SIZE; ++i) {
dc[i].resize(LEVEL2_SIZE);
for (int j = 0; j < LEVEL2_SIZE; ++j) {
dc[i][j].resize(LEVEL3_SIZE);
for (int k = 0; k < LEVEL3_SIZE; ++k) {
dc[i][j][k].resize(LEVEL4_SIZE);
}
}
}
for (int i = 0; i < LEVEL1_SIZE; ++i) {
for (int j = 0; j < LEVEL2_SIZE; ++j) {
for (int k = 0; k < LEVEL3_SIZE; ++k) {
for (int l = 0; l < LEVEL4_SIZE; ++l) {
dc[i][j][k][l] = 0.0;
}
}
}
}
for (int i = 0; i < LEVEL1_SIZE; ++i) {
for (int j = 0; j < LEVEL2_SIZE; ++j) {
for (int k = 0; k < LEVEL3_SIZE; ++k) {
for (int l = 0; l < LEVEL4_SIZE; ++l) {
cout << dc[i][j][k][l] << " ";
}
}
}
}
cout << endl;
return 0;
}