Korrekte Rückgabe eines Objekts

  • Themenstarter Themenstarter C152778
  • Beginndatum Beginndatum
C

C152778

Hallo :)

Hat man eine selbstdefinierte Klasse A und man möchte eine Funktion schreiben, die ein Objekt dieser Klasse zurückgibt, wie geht man am Besten vor?

Ich habe drei Alternativen im Angebot:
Code:
A* methodeXY() {
  // Berechnungen
  A* a = new A(...);
 return a;
}
Wobei ich mir hier unsicher bin, ob der so erstellte Zeiger auf das Objekt vom Typ A innerhalb der Methode nach dem Methodenauffruf nicht ungültig wird ?

Code:
A methodeXY() {
  // Berechnungen
  A* a = new A(...);
  return *a;
Hier wird eine Kopie erstellt, was die Laufzeit drückt.

Code:
void methodeXY(A* a) {
  // Berechnungen
  a = new A(...);
}
Auch hier die Frage, ob der Zeiger nach dem Methodenaufruf noch gültig ist?

Welche Variante ist die eleganteste ? Welche sollte man vorziehen und welche meiden ?

Danke und schöne Grüße, Cyraid

EDIT: Syntaktische Fehler ausgebessert.
 
Zuletzt bearbeitet von einem Moderator:
Wenn du das Objekt selbst zurückgeben willst, warum benutzt du nicht einfach
return *this;
?

Gruß,

badday
 
Hallo Cyraid!

Deine zweite Variante ist syntaktisch nicht korrekt, denn new liefert dir einen Zeiger zurück und kann daher nicht direkt nach A umgewandelt werden.

Deine dritte Variante funktioniert nicht, denn du musst bedenken, dass es sich bei deinem Funktionsargument nur um eine Variable mit dem gleichen Inhalt handelt wie du sie später aufrufst. Daher hat eine Wertzuweisung an dieses lokale Objekt keinen Einfluss auf das Objekt, mit dem du die Funktion aufrufst.

Der Speicher, den du mit new allozierst ist bekanntermassen persistent bis zu einem Aufruf an delete oder dem Programmende.

Für deine dritte Variante gäbe es die Möglichkeit folgendes zu verwenden:
Code:
void CreateInstance(A** ppDest)
{
         if(ppDest == NULL)
                // errorhandling (exception werfen, ...)
         *ppDest = new A;
}

Ich finde das allerdings problematisch, da man blind davon ausgeht, dass das worauf ppDest zeigt ein korrekter Platz ist.

/Edit:
Meine Nummerierungen decken sich leider nicht mit deinen Codesnippets, aber es sollte dennoch klar sein, was gemeint ist ;)
 
Zuletzt bearbeitet:
Ich würde hier einfach einen Smart-Pointer mit Verwendungszähler verwenden.
Wenn du im 1. Versuch das Objekt völlig neu erstellst, kann du das ihne Probleme so machen (soweit ich das sehe), allerdings musst du halt später delete aufrufen.

Gruß,

badday
 
Bei Code 3, das "*A a" soll wohl "A *a" heißen?

Bei Variante 1 bleibt der Pointer gültig, ist soweit ok.
Bei Variante 3 reservierst du Speicher, auf den du nie wieder zugreifen kannst und verstopfst damit nur den Speicher; also weg damit.

Bei Allokierungen in Methoden vergisst man aber leicht aufs freigeben danach.
Besser da freigeben, wo es auch reserviert wird.
 
@Cromon: Danke für deine ausführliche Antwort. :)

Entschuldigung, da haben sich beim schnellen Abtippen ein paar syntaktische Fehler eingeschlichen. Habe sie korrigiert.

Die ausgebesserte 2.Variante wäre also eine gute Art der Realisierung trotz des Kopierens ?

Der Speicher, den du mit new allozierst ist bekanntermassen persistent bis zu einem Aufruf an delete oder dem Programmende.

Stimmt, danke für den Hinweis. Das bedeutet demnach, dass die 1. Variante problemlos funktionieren würde. Gibt es für 1. Variante Nachteile? Ist das ein guter Stil?


Schöne Grüße, Cyraid
 
Nein, die zweite Variante ist sehr schlecht. Der Speicher, den du da allozierst mit new kannst du nie mehr freigeben, da du die Adresse nicht zurückgibst.

Zum Thema kopieren:
Praktisch alle Optimierer optimieren solche Sachen, dass das dennoch über Zeigerrückgabe realisiert wird und der Kopiervorgang unterdrückt wird. Schau dir dazu einfach mal den Assemblercode an, den dein Compiler generiert (am besten zur Laufzeit via Debugger und einem Breakpoint).
 
Nein, die zweite Variante ist sehr schlecht. Der Speicher, den du da allozierst mit new kannst du nie mehr freigeben, da du die Adresse nicht zurückgibst.
Stimmt.

Zum Thema kopieren:
Praktisch alle Optimierer optimieren solche Sachen, dass das dennoch über Zeigerrückgabe realisiert wird und der Kopiervorgang unterdrückt wird. Schau dir dazu einfach mal den Assemblercode an, den dein Compiler generiert (am besten zur Laufzeit via Debugger und einem Breakpoint).

Danke für die Informationen. Demnach ist also eine Variante mit Kopie in Ordnung? Beispielhaft zwei Versionen:
Code:
A methodeXY() {
  // Berechnungen
  A a(...);
 return a;
}

oder

Code:
void methodeXY(A* a) {
  // Berechnungen
  A b(...);
  *a = b;
}

Gibt es zwischen diesen beiden Nachteile/Vorteile ?

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