initialisieren std::string aus char* ohne copy
Ich habe eine situation wo ich brauche große (viele GB) Mengen von Daten wie Z:
- bauen einen großen string durch anfügen viele kleinere (C char*) strings
- schneiden Sie die Zeichenfolge
- konvertieren den string in eine C++ - const std::string für die Verarbeitung (nur Lesen)
- wiederholen
Die Daten in jeder iteration unabhängig sind.
Meine Frage ist, ich möchte zu minimieren (wenn möglich beseitigen) heap reservierten Speicher Nutzung, wie es im moment ist meine größte performance-problem.
Gibt es eine Möglichkeit, zu konvertieren, ein C-string (char*) in einen stl C++ - string (std::string), ohne dass die std::string intern alloc/kopieren der Daten?
Alternativ könnte ich stringstreams oder etwas ähnliches zu re-verwenden Sie einen großen Puffer?
Edit: Danke für die Antworten, zur Klarstellung, ich denke, eine überarbeitete Frage wäre:
Wie kann ich (über mehrere appends) stl C++ - string-effizient. Und wenn Sie diese Aktion ausführen, in einer Schleife, wo jede Schleife ist völlig unabhängig, wie kann ich Sie wieder verwenden thisallocated Raum.
InformationsquelleAutor Akusete | 2008-12-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ist es überhaupt möglich, verwenden Sie einen C++ string in Schritt 1? Wenn Sie
string::reserve(size_t)
können Sie reservieren einen ausreichend großen Puffer, um zu verhindern, dass mehrere heap-Zuweisungen beim anfügen der kleinere strings, und dann können Sie nur verwenden, die denselben C++ - string in allen der verbleibenden Schritte.Sehen dieser link für weitere Informationen über die
reserve
Funktion.Diese Lösung ist die einfachste für mich zu adoptieren, die derzeit, obwohl ich bin mir nicht sicher, ob die re-use ist eigentlich durch die Norm festgelegten (obwohl es scheint zu funktionieren auf meinem Implementierung)
Mit clear() sollte funktionieren. Soweit ich weiß, clear() nicht frei ist der Arbeitsspeicher, der von der Zeichenfolge, und daher keinen Einfluss auf den Speicherplatz von reserve().
Ich weiß, es ist 2.5 Jahre später) Wie lese ich die relevanten Teile der standard, clear() ist definiert in Bezug auf erase () und erase() speziell nicht diktieren, ob der block von Speicher, die nach dem Aufruf von erase() ist die gleiche wie die in bevor dem Aufruf von erase(), noch es vor, dass die Kapazität() bleiben die gleichen. Siehe z.B. 21.3.3 und 21.3.5.5. Vernünftige Implementierungen kann sicherlich funktionieren, aber sicher sein, zu behandeln, es nur als eine nützliche Optimierung-nicht Voraussetzung für richtige Programm funktionieren.
Ritter: Fairer Punkt. Wie immer, die standard-Verfahren ist, um Optimierungen erst nach der Durchführung von Messungen und sicherstellen, dass es notwendig ist. Ich Frage mich, wenn ich sogar wusste, dass Sie zurück in '08?
:)
InformationsquelleAutor e.James
Kann man nicht eigentlich ein std::string, ohne kopieren der Daten. Ein stringstream würde wahrscheinlich Wiederverwendung der Speicher von pass zu pass (obwohl ich denke, dass der standard schweigt sich darüber aus, ob es tatsächlich zu), aber es wäre trotzdem nicht verhindern, dass das kopieren.
Einen gemeinsamen Ansatz, um diese Art von problem ist, den code zu schreiben, welche Prozesse die Daten in Schritt 3 verwenden einen begin/end-iterator-paar, dann kann es leicht verarbeiten, entweder mit einem std::string, ein Vektor von chars, ein paar rohe Zeiger, etc. Im Gegensatz zu der übergabe eines Containers Typ wie std::string, es würde nicht mehr wissen, oder Pflege, wie der Speicher reserviert wurde, da würde es gehören immer noch zu dem Anrufer. Die Durchführung dieser Idee zu seiner logischen Schlussfolgerung ist boost::Angebot, wodurch alle überladene Konstruktoren, noch lassen Sie den Anrufer einfach nur eine Zeichenfolge übergeben/vector/Liste/jede Art von container mit .begin() und .Ende(), oder separate Iteratoren.
Geschrieben haben Ihre Verarbeitung von code auf einem beliebigen iterator-Bereich, dann könnten Sie auch schreiben, eine benutzerdefinierte iterator (nicht so hart wie es klingt, im Grunde nur ein Objekt mit ein paar standard-Typdefinitionen und Betreiber ++/*/=/==/!= überlastet man ein vorwärts-iterator), kümmert sich um die Weiterentwicklung, um das nächste fragment, jedes mal traf es das Ende der es arbeitet, überspringt Leerzeichen (ich nehme an, das ist, was Sie damit gemeint trim). Sie hatte nie zu montieren die gesamte Kette zusammenhängend an alle. Ob oder nicht, dies wäre ein Gewinn hängt davon ab, wie viele Fragmente/aus, wie groß die Fragmente, die Sie haben. Dies ist im wesentlichen, was der SGI Seil erwähnt von Martin York ist: ein string, wo append bildet eine verknüpfte Liste von Fragmenten statt einen zusammenhängenden Puffer ist somit für viel mehr Werte.
UPDATE (da sehe ich immer noch die gelegentliche upvotes auf diese Antwort):
C++17 stellt eine andere Wahl: std::string_view, die ersetzt std::string in vielen Signaturen von Funktionen, ist ein nicht-besitzenden Verweis auf eine Zeichen-Daten. Es ist implizit Cabrio von std::string, kann aber auch explizit konstruiert von zusammenhängenden Daten im Besitz woanders, vermeidet das unnötige kopieren std::string erlegt.
Gibt es ein standard festgelegten Art und Weise zu erreichen-Puffer wiederverwenden? Ich will nur nicht verlassen sich auf die Umsetzung auf eine bestimmte Plattform.
Es sei denn, dass die Verarbeitung code ist eine library-Funktion, die nicht mit Iteratoren noch strings, nur eine einfache alte
char*
+ Größe.InformationsquelleAutor puetzk
Helfen mit wirklich großen strings SGI hat die Klasse Seil in seiner STL.
Nicht standard, kann aber nützlich sein.
http://www.sgi.com/tech/stl/Rope.html
Offenbar Seil ist in der nächsten version von der standard 🙂
Hinweis: die Entwickler Witz. Ein Seil ist eine große Zeichenfolge. (Ha Ha) 🙂
InformationsquelleAutor Martin York
Dies ist ein Querdenken Antwort, die nicht direkt der Beantwortung der Frage, aber "denken" um ihn herum. Vielleicht nützlich, vielleicht nicht...
Readonly-Bearbeitung von std::string nicht wirklich, erfordern eine sehr komplexe Teilmenge von std::string-Funktionen. Gibt es eine Möglichkeit, dass Sie könnte suchen/ersetzen im code, führt alle Verarbeitung auf std::strings, so dauert es einige anderen Art statt? Sie starten mit einer leeren Klasse:
Klasse lightweight_string { };
Dann alle ersetzen std::string-Referenzen mit lightweight_string. Führen Sie eine Zusammenstellung, um genau herauszufinden, welche Operationen erforderlich sind, auf lightweight_string für es als drop-in Ersatz. Dann können Sie Ihre Implementierung arbeiten, aber Sie wollen.
InformationsquelleAutor Daniel Earwicker
Ist jeder iteration unabhängig genug, dass Sie können verwenden die gleichen std::string für jede iteration? Man würde hoffen, dass dein std::string Implementierung ist smart genug, um re-use Speicher bei der Zuweisung einer const char *, wenn es vorher verwendet wurde, für etwas anderes.
Zuweisung eines char * in einen std::string muss immer mindestens die Daten kopieren. Speicher-management ist einer der wichtigsten Gründe für die Verwendung von std::string, so dass Sie nicht in der Lage, um es zu überschreiben.
InformationsquelleAutor David Norman
In diesem Fall könnte es besser sein, einen Prozess der char* direkt, statt der Zuweisung an einen std::string.
InformationsquelleAutor Alan