STL Swap bei Rückgabe?

8

Entschuldigung für solch eine lange Frage, aber ich versuche so klar wie möglich zu sein. Dies folgt irgendwie meiner vorherigen Frage zu Zeichenketten in C ++ . Ich versuche herauszufinden, wie ich std :: string von einer Funktion ohne redundante Speicherzuweisungen zurückgeben kann, ohne auf NRVO angewiesen zu sein. Die Gründe, warum ich mich nicht auf NRVO verlassen will, sind:

  • es wird nicht von dem Compiler unterstützt, den wir derzeit verwenden
  • selbst wenn es unterstützt wird, ist es möglicherweise nicht immer im Debug-Modus aktiviert
  • kann in einigen Fällen fehlschlagen ( Beispiel )

Bitte beachten Sie, dass ich eine C ++ 03 kompatible Lösung brauche (leider keine C ++ 0x rvalue Referenzen, also ...)

Der einfachste Weg ist das Pass-by-Reference-Verfahren und std :: swap, wie folgt

%Vor%

Aber es ist natürlicher und oft bequemer, nach Wert zurückzukehren, als durch Verweis zu übergeben. Was ich also erreichen möchte, ist dies:

%Vor%

Idealerweise würde es nur eine swap mit dem "Rückgabewert" machen, aber ich sehe nicht, wie man das in C ++ macht. Es gibt bereits auto_ptr, das sich bewegt anstatt zu kopieren, und ich könnte tatsächlich auto_ptr<string> verwenden, aber ich möchte es vermeiden, das String-Objekt selbst dynamisch zuzuweisen.

Meine Idee ist es, ein String-Objekt, das von einer Funktion zurückgegeben wird, irgendwie zu "taggen", um das Verschieben seiner Daten zu erlauben, wenn ein Copy-Konstruktor bei der Rückgabe aufgerufen wird. Also habe ich diesen Code, der genau das tut, was ich will:

%Vor%

Also ... Macht das alles Sinn oder gibt es einige ernste Probleme, die ich vermisse? (Ich bin mir nicht sicher, ob es zum Beispiel kein lebenslanges Problem gibt). Vielleicht haben Sie eine solche Idee bereits in einer Bibliothek (Buch, Artikel ...) gesehen und könnten mir einen Hinweis darauf geben?

BEARBEITEN: Wie @rstevens bemerkt hat, ist dieser Code MSVC-spezifisch und wird nicht unter g ++ kompiliert, was das nicht-konstante temporäre nicht mag. Dieses ist ein Problem, aber nehmen wir an, diese Implementierung ist MSVC-spezifisch.

    
Roman L 19.01.2011, 17:05
quelle

3 Antworten

4

Die Implementierung von boost verwendet die Semantikemulation intern für Bibliotheken wie Boost.Thread . Vielleicht möchten Sie sich die Implementierung ansehen und etwas ähnliches tun.

Bearbeiten: Es gibt tatsächlich eine aktive Entwicklung einer Bibliothek Boost.Move , damit Sie bereits anfangen können, es zu benutzen.

    
ybungalobill 19.01.2011, 17:12
quelle
1

Hast du diesen Code auf g ++ überprüft?

Da Sie Str (Movable & amp;) mit einem temporären Objekt (das von s.Move () zurückgegebene) aufrufen!

Dies ist nicht standardkonform und wird nicht von g ++ unterstützt. Es wird von MSVC unterstützt! (MS nennt dies eine Funktion ...).

    
mmmmmmmm 19.01.2011 20:19
quelle
0

Haben Sie tatsächlich festgestellt, dass die Rückgabe nach Wert ein Leistungsproblem in Ihrer Anwendung ist? Das scheint der einfachste / einfachste Weg zu sein, und wenn Sie auf einen moderneren Compiler aufrüsten, können Sie rvalue-Referenzen verwenden.

Ich kann die Frage bezüglich der Zerstörungsreihenfolge von s gegenüber der Movable Referenz nicht beantworten. Sie könnten für Ihren Compiler Code in die verschiedenen Konstruktoren und Destruktoren einfügen, um zu sehen, um was für eine Reihenfolge es sich handelt. Selbst wenn es in Ordnung aussieht, würde ich trotzdem in Betracht ziehen, eines der normalen Muster zu verwenden, die du umrissen hast, nur um Verwirrung beim Leser zu vermeiden und möglicherweise einen alternativen Compiler zu knacken.

    
Mark B 19.01.2011 18:29
quelle