Ich würde mir darüber keine Sorgen machen. Wenn Sie dies in einer Schleife tun, weisen Zeichenfolgen immer Speicher zu, um Neuzuweisungen zu minimieren. Verwenden Sie dies nur operator+=
in diesem Fall. Und wenn Sie es manuell tun, so etwas oder länger
a + " : " + c
Dann werden temporäre Dateien erstellt - auch wenn der Compiler einige Kopien von Rückgabewerten entfernen könnte. Dies liegt daran, dass in einem nacheinander aufgerufenen operator+
Objekt nicht bekannt ist, ob der Referenzparameter auf ein benanntes Objekt oder ein von einem Unteraufruf zurückgegebenes temporäres Objekt verweist operator+
. Ich würde mir lieber keine Sorgen machen, bevor ich nicht zuerst ein Profil erstellt habe. Aber nehmen wir ein Beispiel, um das zu zeigen. Wir führen zuerst Klammern ein, um die Bindung klar zu machen. Ich setze die Argumente direkt nach der Funktionsdeklaration, die der Klarheit halber verwendet wird. Darunter zeige ich, was der resultierende Ausdruck dann ist:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
In diesem Zusatz tmp1
wurde nun der erste Aufruf von operator + mit den angezeigten Argumenten zurückgegeben. Wir gehen davon aus, dass der Compiler wirklich clever ist und die Rückgabewertkopie optimiert. Am Ende haben wir also eine neue Zeichenfolge, die die Verkettung von a
und enthält " : "
. Nun passiert dies:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
Vergleichen Sie das mit Folgendem:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
Es verwendet dieselbe Funktion für eine temporäre und eine benannte Zeichenfolge! Der Compiler muss also das Argument in eine neue Zeichenfolge kopieren und an diese anhängen und aus dem Hauptteil von zurückgeben operator+
. Es kann nicht die Erinnerung an eine temporäre nehmen und daran anhängen. Je größer der Ausdruck ist, desto mehr Kopien von Zeichenfolgen müssen erstellt werden.
Next Visual Studio und GCC unterstützen die Verschiebungssemantik von c ++ 1x (ergänzt die Kopiersemantik ) und die rvalue-Referenzen als experimentelle Ergänzung. Auf diese Weise können Sie herausfinden, ob der Parameter auf ein temporäres Element verweist oder nicht. Dies wird solche Ergänzungen erstaunlich schnell machen, da alle oben genannten in einer "Add-Pipeline" ohne Kopien enden werden.
Wenn sich herausstellt, dass es sich um einen Engpass handelt, können Sie dies dennoch tun
std::string(a).append(" : ").append(c) ...
Die append
Aufrufe hängen das Argument an *this
und geben dann einen Verweis auf sich selbst zurück. Dort wird also kein Provisorium kopiert. Alternativ operator+=
kann das verwendet werden, aber Sie benötigen hässliche Klammern, um die Priorität festzulegen.