Objekterückgabe einer Funktion

  • Themenstarter Themenstarter C152778
  • Beginndatum Beginndatum
C

C152778

Hallo,

mich würde gerne interessieren, ob folgende string Rückgabe Sinn ergibt ?
Code:
string&  myFunction() {
  string s = "Hallo";
  return  s;
}

Sehe ich es richtig, dass man so eine Funktion nicht schreiben sollte, da das Objekt s innerhalb der Funktion zerstört wird sobald die Funktion verlassen wird ?
Oder wird das Objekt s am Leben erhalten, da noch eine Referenz auf dieses besteht durch die Rückgabe der Referenz auf s ?

Schöne Grüße, Cyraid
 
Richtig, das Objekt wird am Ende der Funktion zerstört. Dass eine Referenz existiert, merkt sich das Programm nicht, glaube ich.
In diesem Fall braucht man (wie du sicher schon vermutest) eine Rückgabe per Kopie, oder einen Parameter in der Funktion (mit Referenz oder Pointer).
 
Zuletzt bearbeitet:
Das Objekt kann gar nicht am Leben gehalten werden, denn es befindet sich auf dem Stack und dieser wird nach der Funktion wieder aufgeräumt.

/Edit
Schau dir dazu mal die Hybridassembly für primitive Referenzrückgaben (int&, float&, char&, ...) und auch Referenzparameter an. Da erkennst du dann schnell, dass & zu * wird und der Zeiger auf den Stack zeigt, der dann mit dem Epilog der Funktion invalidiert wird.
 
Zunächst vielen Dank für eure Antworten. :)

Ich habe gerade einmal in der C++ Standard Bibliothek geschaut und gesehen, dass beispielsweise die string Klasse bei der at Funktion einen const char& liefert.
URL: http://www.cplusplus.com/reference/string/string/at/

Ist das dann aber nicht ein wenig "gefährlich" ?
Denn wenn ich ein string Objekt erzeuge, mir eine Referenz auf einen char hole, dann aber das string Objekt zerstört wird, ist meine char Variable nicht in einem invaliden Zustand ? Oder übersehe ich hier etwas?

Schöne Grüße, Cyraid
 
C++:
class string
{
      char* _myPtr; // = der aktuelle Inhalt des Strings
public:
      const char& at(int index)
      {
              if(index < _myLen)
                    return _myPtr[index];
              throw std::out_of_range();
      }
};

Bei Klassen müsstest du immer schauen, was zurückgegeben wird, da es theoretisch Klassenlebenszeit haben kann.
 
@Cromon: Danke für deine Antwort. D.h. also es kann z.B. bei der at Methode der string Klasse tatsächlich dazu kommen, dass nach der Zerstörung des string Objekts die Referenz auf den char ungültig wird?

Schöne Grüße, Cyraid
 
Bei Klassen müsstest du immer schauen, was zurückgegeben wird, da es theoretisch Klassenlebenszeit haben kann.
Du meinst vermutlich Objektlebenszeit oder Instanzlebenszeit. Klassen haben in dem Sinne keine Lebenszeit.

@Cromon: Danke für deine Antwort. D.h. also es kann z.B. bei der at Methode der string Klasse tatsächlich dazu kommen, dass nach der Zerstörung des string Objekts die Referenz auf den char ungültig wird?
Ja. Wenn du eine Kopie des chars anlegst anstatt eine Referenz zu speichern, bist du aber auf der sicheren Seite.

Grüße,
Matthias
 
Ja genau, Matthias, aber du musst zugeben, "Klassenlebenszeit" ist doch auch eine interessante Verbindung :D

@Cyraid:
Nicht nur kann es dazu kommen, sondern es wird dazu kommen. Vorausgesetzt ist natürlich, dass std::string sauber programmiert wurde und sozusagen _MyPtr auch entsprechend gelöscht wird. Wird das nicht gemacht dürfte eigentlich deine Referenz noch gültig sein (das ist nicht gut, sondern schlecht).
 
Es gäbe da auch noch die Möglichkeit eine Kopie zurückzugeben:
PHP:
std::string testFunc()
{
	std::string testStr("Hallo Welt!");
	return testStr;
}

void main()
{
	std::string test = testFunc();
}

Oder du gibst eine neue Instanz zurück, die dann aber ausserhalb wieder gelöscht werden muss:

PHP:
std::string *testFunc()
{
	std::string *testStr = new std::string("Hallo Welt!");
	return testStr;
}

void main()
{
	std::string *test = testFunc();
	delete test;
}

Mfg Pain-maker
 
Vielen Dank für eure aufklärenden und guten Antworten ! :)
Das hat mir schon sehr geholfen.

Mich wundert es allerdings ein wenig, dass die Standardbibliothek z.B. bei der at Funktion von string es dem Programmierer überlässt "vorsichtig" mit der Referenz umzugehen bzw. eine Kopie anzulegen. Warum gibt die at Funktion nicht direkt eine Kopie zurück, wenn die Referenz unsicherer ist?
Oder steht hier der sparsame Einsatz des Speichers (Kopie => doppelter Speicher) im Vordergrund?

Gerade sehe ich, dass beispielsweise die push_back Funktion der vector Klasse einen const T& Parameter entgegen nimmt.
Wäre ja etwas gefährlich, da auch hier die Referenz invalide werden könnte und das vector Objekt so evtl einen ungültigen Eintrag besitzt.
Dann habe ich jedoch unter
http://www.cplusplus.com/reference/stl/vector/push_back/

gelesen, dass eine Kopie des übergebenen Parameters angelegt wird. Damit ist es ungefährlich geworden.

Ich möchte mich gerne vergewissern, ob ich es richtig verstanden habe: Würde die vector Klasse hier keine Kopie anlegen, wäre es also möglich, dass der vector evtl ungültige Referenzen speichert ?

Schöne Grüße, Cyraid
 
Zurück