Frage

Ich bin ziemlich neu in C ++, aber ich weiß, Sie können nicht nur Speicher verwenden, nolens volens, wie die Klasse std :: string scheinen Sie tun zu lassen. Zum Beispiel:

std::string f = "asdf";
f += "fdsa";

Wie funktioniert die String-Klasse Handle immer größer und kleiner? Ich nehme an, es eine Standard-Speichermenge zuweist und wenn es mehr braucht, es news einen größeren Speicherblock und kopiert sich über dem. Aber wäre das nicht ziemlich ineffizient zu sein, die gesamte Zeichenkette, die es jedes Mal zu haben, kopieren erforderlich, um die Größe? Ich kann nicht wirklich denken Sie an eine andere Art und Weise es getan werden könnte (aber offensichtlich jemand tat).

Und was das betrifft, wie alles tun, die stdlib Klassen wie Vektor, Warteschlange, Stapel, etc Griff wachsen und so transparent schrumpfen?

War es hilfreich?

Lösung

In der Regel gibt es eine Verdoppelung Algorithmus. Mit anderen Worten, wenn es den aktuellen Puffer füllt, weist es einen neuen Puffer, die doppelt so groß ist, und kopiert dann die aktuellen Daten über. Dies führt zu weniger zuteil / Kopieroperationen als die Alternative von einem einzigen Zuordnungsblock wächst.

Andere Tipps

Ihre Analyse ist richtig - es is ineffizient die Zeichenfolge jedes Mal zu kopieren, sie braucht, um die Größe. Deshalb gemeinsame Beratung entmutigt, dass die Verwendung Muster. Verwenden Sie die Zeichenfolge reserve Funktion es zu fragen, genügend Speicher zuweisen, was Sie beabsichtigt in ihnen zu speichern. Dann weitere Operationen werden, dass der Speicher füllen. (Aber wenn Ihr Hinweis erweist sich als zu klein zu sein, wird die Zeichenfolge noch automatisch wachsen, auch.)

Container werden auch in der Regel versuchen, die Auswirkungen der häufigen Neuzuweisung zu mildern, indem mehr Zuweisen von Speicher, als sie benötigen. Ein gemeinsamer Algorithmus ist, dass, wenn eine Zeichenfolge fest, dass es Platz ist out, es Doppel seine Puffergröße, anstatt nur die minimale Zuteilung erforderlich, um den neuen Wert zu halten. Wenn die Zeichenkette ein Zeichen zu einer Zeit wachsen gelassen wird, diese Verdoppelung Algorithmus reduziert die Zeit, die Komplexität zu fortgeführten linearen Zeit (anstelle der quadratischen Zeit). Es verringert auch die Anfälligkeit des Programms Speicherfragmentierung.

Obwohl ich weiß nicht, die genaue Umsetzung von std :: string, die meisten Datenstrukturen, die Notwendigkeit, dynamische Speicherwachstum zu handhaben dies tun, indem genau das tun, was Sie sagen - eine Standardspeichermenge zuzuweisen, und wenn mehr benötigt wird, dann erstellen ein größerer Block und kopieren Sie sich über.

Die Art und Weise Sie das offensichtliche Ineffizienz Problem umgehen, ist mehr Speicher zuzuweisen, als Sie benötigen. Das Verhältnis der verwendeten Speicher: Gesamtspeicher eines Vektors / string / Liste / etc wird oft den Lastfaktor (auch für Hash-Tabellen in einer etwas anderen Bedeutung verwendet) genannt. Normalerweise ist es ein 1: 2-Verhältnis - das heißt, Sie zuweisen zweimal den Speicher, den Sie benötigen. Wenn Sie genügend Speicherplatz aus, weisen Sie einen neuen Speichermenge zweimal Ihre aktuelle Höhe und Verwendung der. Dies bedeutet, dass im Laufe der Zeit, wenn Sie weiterhin die Dinge auf den Vektor / string hinzufügen / etc, müssen Sie weniger das Objekt kopieren über und weniger (wie die Speicher Schöpfung ist exponentiell, und Ihre Einfügen neuer Elemente ist natürlich linear), und so die Zeit für diese Art der Speicherverwaltung genommen ist nicht so groß wie Sie vielleicht denken. Durch den Grundsätzen der Amortisierte Analyse , können Sie dann sehen, dass m Elemente in einen Vektor / string Einfügen / Liste dieser Methode ist nur Big-Theta von m, nicht m 2 .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top