Wie std :: string korrekt zurückgegeben wird (oder wie der zurückgegebene Wert richtig verwendet wird)

8

Angenommen, Sie haben eine Klasse, die global ist (z. B. verfügbar für die Laufzeit der App)

%Vor%

Wenn ich die erste Form benutze, bekomme ich seltsames Verhalten, wenn ich es mache

%Vor%

Es sieht so aus, als ob die Zeichenfolge aus dem Speicher verschwindet, bevor sie von printf verwendet werden kann. Manchmal druckt es Wert: hallo andere Male stürzt es ab oder druckt nichts.

Wenn ich die Zeichenfolge zuerst so kopiere wie

%Vor%

Dinge funktionieren.

Sicherlich muss es eine Möglichkeit geben, dies mit einer temporären Zeichenfolge zu vermeiden.

Edit: Der Konsens besteht also darin, mit einem const std :: string & amp; Rückgabewert.

Ich weiß, dass jeder sagt, dass der ursprüngliche Code in Ordnung sein sollte, aber ich kann dir das sagen Ich habe gesehen, MSVC 2005 auf Windows CE Probleme damit, aber nur auf der CE-Box. Nicht das Win32-Kreuz kompilieren.

    
Ron 06.01.2011, 22:08
quelle

4 Antworten

6

Ihr Code sollte gut funktionieren. Etwas anderes ist falsch, das wir aus diesem Testfall nicht erkennen können. Führen Sie Ihre ausführbare Datei möglicherweise über Valgrind aus, um nach Speicherfehlern zu suchen.

    
quelle
1

Nun, es ist nichts falsch mit dem Code (wie ich es interpretiere). Es ist nicht optimal und sicher nicht The Right Way (R) , Sie sollten Ihren Code ändern, wie villentehaspam suggeriert. Wie es jetzt ist, erstellt Ihr Code eine Kopie der Zeichenfolge m_value , weil Sie nach Wert zurückgeben, was nicht so gut ist, als würde nur eine const-Referenz zurückgegeben.

Wenn Sie ein vollständiges Codebeispiel bereitstellen, das das Problem anzeigt, könnte ich Ihnen besser helfen.

    
rubenvb 06.01.2011 22:18
quelle
0

nicht, dass es wichtig ist, aber dass std :: string return in dieser Klasse kann eine const anderen weise Sie erstellen nur eine Kopie des Mitglieds Wert, der eine Verschwendung ist.

%Vor%     
graphitemaster 07.01.2011 17:02
quelle
-1

Hier ist, was passiert, wenn Sie schreiben:

%Vor%
  1. Der Compiler erstellt einen temporären std::string , um den von v1.value() zurückgegebenen Wert zu speichern.
  2. Er ruft v1.value() auf und gibt seinen Rückgabewert in die temporäre Zeichenfolge ein (genau wie dies variieren kann: In der Regel wird ein Verweis auf das Temporäre als versteckter Parameter an die Methode übergeben. Siehe Ссылка zur Diskussion).
  3. Es ruft .c_str() auf dem temporären std::string auf, es speichert das const char * Ergebnis irgendwo weg (z. B. ein Register).
  4. Es ist jetzt fertig mit dem temporären std::string , zerstört es also (d. h. ruft seinen Destruktor auf, gibt vielleicht etwas Stapelspeicher frei).
  5. Er übergibt den const char * -Zeiger, den er in Schritt (3) erhalten hat, als Argument an printf() .

Das Problem besteht darin, dass der Zeiger in Schritt 3 auf Speicher zeigt, der von dem temporären std::string zugewiesen wurde, das freigegeben wird, wenn der Destruktor des temporären aufgerufen wird. Dieser Speicher kann zu dem Zeitpunkt, zu dem er von printf() verwendet wird, schon lange weg sein.

Grundsätzlich ist jede Verwendung wie die, die Sie gezeigt haben, gefährlich und sollte vermieden werden. Folgendes ist richtig:

%Vor%

weil der Destruktor für copiedString erst aufgerufen wird, wenn copiedString den Gültigkeitsbereich verlässt, einige Zeit nachdem printf() zurückgegeben wurde. Tatsächlich ist dies nicht weniger effizient als v1.value().c_str() , weil in jedem Fall ein temporäres std::string erzeugt wird.

Die Rückgabe eines Verweises auf einen String ist eine gute Alternative, vorausgesetzt, dass der Verweis so lange gültig bleibt, wie der Anrufer ihn benötigt. Ein Verweis auf eine Elementvariable in einem langlebigen Objekt ist also OK. ein Hinweis auf etwas, das sich als vorübergehend herausstellt, ist es nicht.

    
Ian Harvey 22.04.2014 14:03
quelle

Tags und Links