2017-03-21 3 views
1

Wenn ein Vektor immer zusammenhängenden Speicher bereitstellt, wie reserviert der Compiler Speicher leer std :: strings?Speicherzuweisung für Zeichenfolgen in Vektoren

Ich habe einen Vektor, an den ich eine Reihe von Klassen mit Std: String als ein privates Mitglied geschoben habe. Ich übergebe dann einen Verweis auf den Vektor als Argument für eine andere Methode.

Sind die Daten der Zeichenfolge an anderer Stelle im Heap, auf den vom zusammenhängenden Array des Vektors verwiesen wird?

Antwort

3

Zuweisungsspeicher für std::string ist trivial.

Intern wird es eine Art Zeiger haben, der auf einen Speicherblock zeigt, in dem die tatsächlichen String-Daten gespeichert werden. Also, Speicher für eine std :: string Zuweisung ist einfach eine Frage der Zuweisung von Platz für einen Zeiger, ein size_t oder etwas, und vielleicht ein paar mehr Primitiven.

Wenn Sie ein std::vector<std::string> zum Beispiel haben, ist es einfach für den Vektorraum für die std::string ‚s reservieren, da sie nur k Bytes jeweils für eine Konstante k sind. Die Zeichenkettendaten sind an dieser Zuordnung nicht beteiligt.

1

Die Details, was in diesem Fall wirklich im Speicher passiert, hängen stark von der spezifischen STL-Implementierung ab, die Sie verwenden.

auch sagen, dass mein Eindruck ist, dass wie (sehr vereinfacht) mit etwas in den meisten Implementierungen Vektor und String sind implementiert:

template<typename T> 
class vector 
{ 
    //... 
    private: 
    T* _data; 
}; 

class string 
{ 
    private: 
    char _smallStringsBuffer[kSmallSize]; 
    char* _bigStringsBuffer; 
}; 

Die Daten des Vektors dynamisch auf dem Heap auf der Basis der Kapazität zugewiesen wird (Das hat einen Standardwert wenn default-initialisiert, und wächst, während Sie Elemente zum Vektor hinzufügen).

Die Daten der Zeichenfolge werden statisch für kleine Zeichenfolgen (implementierungsabhängiger Wert von "klein") zugewiesen, und dann dynamisch, wenn die Zeichenfolge größer wird. Dies ist aus einer Reihe von Gründen der Fall, hauptsächlich jedoch um eine effizientere Handhabung von kleinen Strings zu ermöglichen.

Das Beispiel, das Sie beschrieben ist so etwas wie:

void MyFunction(const vector<string>& myVector) 
{ 
    // ... 
} 

int main() 
{ 
    vector<string> v = ...; 

    // ... 

    MyFunction(v); 

    // ... 

    return 0; 
} 

In diesem speziellen Fall nur die Basisdaten des Vektors v in dem Stapel wird, wie v._data auf dem Heap zugewiesen werden. Wenn v die Kapazität N hat, ist die Größe von v._data im Heap sizeof (string) * N, wobei die Größe des Strings eine Konstante ist, die von kSmallSize * sizeof (char) + sizeof (char *) abhängt. basierend auf der Definition der obigen Zeichenfolge.

Bei zusammenhängenden Daten, nur wenn alle im Vektor gesammelten Zeichenketten weniger Zeichen als kSmallSize haben, sind ihre Daten "fast" zusammenhängend im Speicher.

Dies ist eine wichtige Überlegung für leistungskritischen Code, aber um ehrlich zu sein glaube ich nicht, dass die meisten Menschen auf Standard-STL-Vektoren und Strings für solche Situationen verlassen würden, da sich die Implementierungsdetails im Laufe der Zeit ändern können Plattformen und Compiler. Darüber hinaus werden Sie, wenn Ihr Code den "schnellen" Pfad verlässt, nicht bemerken, außer mit Latenzspitzen, die schwer zu kontrollieren sind.