Meine Frage ist einfach: Sind std :: vector-Elemente garantiert zusammenhängend? Kann ich den Zeiger auf das erste Element eines std :: -Vektors als C-Array verwenden?
Wenn mein Gedächtnis mir gut tut, hat der C ++ - Standard keine solche Garantie gegeben. Die Anforderungen an std :: vector waren jedoch so, dass es praktisch unmöglich war, sie zu erfüllen, wenn die Elemente nicht zusammenhängend waren.
Kann jemand das klären?
Beispiel:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
values
in diesemif
Block mutieren . Ich kenne die Antwort auf Ihre Frage jedoch nicht und hinterlasse nur einen Kommentar. :)values
, die ihre Größe ändern (z. B.push_back()
), können zu einer Neuzuweisung des zugrunde liegenden Vektors führen, wodurch der kopierte Zeiger ungültig wirdarray
. Es ist das gleiche Prinzip wie bei der Verwendung eines vector :: iterator anstelle eines Zeigers in den Vektor. :)Antworten:
Dies wurde im eigentlichen C ++ 98-Standard übersehen, aber später als Teil eines TR hinzugefügt. Der bevorstehende C ++ 0x-Standard wird dies natürlich als Voraussetzung enthalten.
Ab n2798 (Entwurf von C ++ 0x):
quelle
std::vector
, die zusammenhängend sind. ZB .: instd::vector<std::vector<int>> v
den Elementenv[0]
,v[1]
... wird anschließend in einem Speicher gespeichert, aber das Elementv[0].back()
undv[1].front()
nicht als garantiert.Wie andere Antworten gezeigt haben, ist der Inhalt eines Vektors garantiert kontinuierlich (mit Ausnahme der Verrücktheit von Bool).
Der Kommentar, den ich hinzufügen wollte, lautet: Wenn Sie den Vektor einfügen oder löschen, wodurch der Vektor seinen Speicher neu zuordnen kann, werden alle Ihre gespeicherten Zeiger und Iteratoren ungültig.
quelle
Der Standard garantiert tatsächlich, dass a
vector
im Speicher kontinuierlich ist und&a[0]
an eineC
Funktion übergeben werden kann, die ein Array erwartet.Die Ausnahme von dieser Regel ist,
vector<bool>
dass nur ein Bit pro verwendet wird,bool
obwohl es einen kontinuierlichen Speicher hat, kann es nicht als verwendet werdenbool*
(dies wird allgemein als falsche Optimierung und als Fehler angesehen).Übrigens, warum benutzt du keine Iteratoren? Dafür sind sie da.
quelle
Wie andere bereits gesagt haben, wird
vector
intern eine zusammenhängende Anordnung von Objekten verwendet. Zeiger in dieses Array sollten immer dann als ungültig behandelt werden, wenn eine nicht konstante Mitgliedsfunktion als IIRC bezeichnet wird.Es gibt jedoch eine Ausnahme !!
vector<bool>
hat eine spezielle Implementierung, die Platz spart, so dass jeder Bool nur ein Bit verwendet. Das zugrunde liegende Array ist kein zusammenhängendes Array von Bool, und die Array-Arithmetikvector<bool>
funktioniert nicht wievector<T>
gewünscht.(Ich nehme an, es ist auch möglich, dass dies für jede Spezialisierung von Vektoren gilt, da wir immer eine neue implementieren können. Dies
std::vector<bool>
ist jedoch die einzige, ähm, Standardspezialisierung, bei der einfache Zeigerarithmetik nicht funktioniert.)quelle
std::vector
, und alle anderen Vektoren müssen zusammenhängenden Speicher verwenden. Daherstd::vector<bool>
ist (zum Glück) der einzige Standardvektor, der seltsam ist. (Ich bin der festen Überzeugung, dass diese Spezialisierung veraltet und durch z. B. einestd::dynamic_bitset
mit nahezu der gleichen Funktionalität ersetzt werden sollte. Es ist keine schlechte Datenstruktur, es ist nur kein Vektor.)Ich habe diesen Thread gefunden, weil ich einen Anwendungsfall habe, bei dem Vektoren, die zusammenhängenden Speicher verwenden, von Vorteil sind.
Ich lerne, wie man Vertex-Pufferobjekte in OpenGL verwendet. Ich habe eine Wrapper-Klasse erstellt, die die Pufferlogik enthält. Ich muss also nur ein Array von Floats und einige Konfigurationswerte übergeben, um den Puffer zu erstellen. Ich möchte in der Lage sein, einen Puffer aus einer Funktion basierend auf Benutzereingaben zu generieren, daher ist die Länge zur Kompilierungszeit nicht bekannt. So etwas zu tun wäre die einfachste Lösung:
Jetzt kann ich die Floats des Vektors als Array an die pufferbezogenen Funktionen von OpenGL übergeben. Dadurch entfällt auch die Notwendigkeit von sizeof, um die Länge des Arrays zu bestimmen.
Dies ist weitaus besser, als ein großes Array zum Speichern der Floats zuzuweisen und zu hoffen, dass ich es groß genug gemacht habe, oder mein eigenes dynamisches Array mit zusammenhängendem Speicher zu erstellen.
quelle
v
und nicht auf sichv
selbst übergeben? Wenn Siev
alleine übergeben, wird eine Kopie innerhalb der Funktion erstellt, die nach Beendigung der Funktion nicht mehr vorhanden ist. Sie drücken also etwas auf den Vektor, um den Vektor nur zu löschen, wenn die Funktion endet.cplusplus.com:
quelle
Ja, die Elemente eines std :: vector sind garantiert zusammenhängend.
quelle