Bevor Sie beginnen, prüfen Sie, ob in dieser Funktion viel Zeit verbraucht wird. Tun Sie dies, indem Sie entweder mit einem Profiler oder auf andere Weise messen. Zu wissen, dass Sie es eine Zillion Mal nennen, ist alles sehr gut, aber wenn es sich herausstellt, dass Ihr Programm nur 1% seiner Zeit in dieser Funktion ausgibt, dann kann nichts, was Sie hier tun, Ihre Programmleistung um mehr als 1% verbessern. Wenn das der Fall wäre, wäre die Antwort auf Ihre Frage "für Ihre Zwecke nein, diese Funktion kann nicht wesentlich effizienter gemacht werden und Sie verschwenden Ihre Zeit, wenn Sie es versuchen".
Als erstes meiden Sie s.substr(0, s.size()-1)
. Dies kopiert den größten Teil der Zeichenkette und es macht Ihre Funktion für NRVO ungeeignet, also denke ich, dass Sie normalerweise eine Kopie bei der Rückkehr bekommen werden. Also die erste Änderung, die ich machen würde, ist die letzte Zeile zu ersetzen mit:
Aber wenn Leistung eine ernsthafte Sorge ist, dann ist hier, wie ich es tun würde. Ich verspreche nicht, dass dies die schnellste Möglichkeit ist, aber es vermeidet einige Probleme mit unnötigen Zuweisungen und Kopieren. Jeder Ansatz, der stringstream
involviert, wird eine Kopie vom Stringstream zum Ergebnis benötigen, also wollen wir eine Operation auf niedrigerer Ebene, snprintf
.
Der zweite Aufruf von snprintf
setzt voraus, dass std::string
zusammenhängenden Speicher verwendet. Dies ist in C ++ 11 garantiert. Es ist nicht in C ++ 03 garantiert, aber gilt für alle aktiv gepflegten Implementierungen von std::string
, die dem C ++ - Committee bekannt sind. Wenn Leistung wirklich wichtig ist, dann ist es vernünftig, diese nicht-portable Annahme zu machen, da das direkte Schreiben in eine Zeichenkette später das Kopieren in eine Zeichenkette speichert.
s.pop_back()
ist der C ++ 11-Weg, um s.erase(s.end()-1)
zu sagen, und s.back()
ist s[s.size()-1]
Für eine weitere mögliche Verbesserung könnten Sie den ersten Aufruf von snprintf
loswerden und stattdessen Ihre s
auf einen Wert wie std::numeric_limits<double>::max_exponent10 + 14
(im Grunde die Länge, die -DBL_MAX
hat) Bedürfnisse). Das Problem ist, dass dies viel mehr Speicher reserviert und löscht, als normalerweise benötigt wird (322 Bytes für ein IEEE-Double). Meine Intuition ist, dass dies langsamer sein wird als der erste Aufruf von snprintf
, ganz zu schweigen von verschwenderischem Speicher, wenn der String-Rückgabewert eine Weile vom Aufrufer gehalten wird. Aber du kannst es immer testen.
Alternativ berechnet std::max((int)std::log10(d), 0) + 14
eine relativ enge Obergrenze für die benötigte Größe und ist möglicherweise schneller als snprintf
kann sie genau berechnen.
Schließlich kann es sein, dass Sie die Leistung verbessern können, indem Sie die Funktionsschnittstelle ändern. Anstatt beispielsweise eine neue Zeichenfolge zurückzugeben, könnten Sie sie an eine Zeichenfolge anhängen, die vom Aufrufer übergeben wurde:
%Vor% Dann kann der Aufrufer reserve()
viel Platz haben, rufen Sie Ihre Funktion mehrmals (vermutlich mit anderen String-Anhängen dazwischen), und schreiben Sie den resultierenden Datenblock auf einmal in die Datei, ohne eine andere Speicherbelegung als die %Code%. "Plenty" muss nicht die ganze Datei sein, es könnte jeweils eine Zeile oder ein "Absatz" sein, aber alles, was eine Unmenge von Speicherzuweisungen vermeidet, ist ein potenzieller Leistungsschub.
snprintf
und ein Array von char
anstelle von stringstream
und string
char
buffer an dbl2str, in den er gedruckt wird (um zu vermeiden, dass der Kopierkonstruktor von string
beim Zurückgeben aufgerufen wird). Stellen Sie die zu druckende Zeichenfolge in einem Zeichenpuffer zusammen (oder konvertieren Sie den Zeichenpuffer beim Aufrufen in eine Zeichenfolge oder fügen Sie ihn einer vorhandenen Zeichenfolge hinzu) deklarieren Sie die Funktion inline
in einer Header-Datei
Tags und Links c++ stringstream