Was ist eine gute Richtlinie für die Verwendung von "neu", um eine Instanz einer Klasse zu erstellen? Ich habe schon eine Weile C ++ programmiert, aber ich bin mir noch nicht sicher, wann der beste Zeitpunkt dafür ist:
%Vor%darüber:
%Vor%Irgendwelche Ratschläge?
Der Unterschied liegt hier:
%Vor%Bei großen Objekten müssen Sie Speicher dynamisch zuweisen (new), da der Prozessstapel eine begrenzte Größe hat.
Design-weise verwenden so oft wie möglich die automatische (Stapel-) Zuweisung . Wann immer Sie die Lebensdauer eines Objekts über einen bestimmten Bereich hinaus verlängern müssen, ordnen Sie es dynamisch zu.
Und trotzdem sollten Sie Dinge niemals dynamisch roh zuweisen. Lassen Sie sie immer in eine Art Wrapper verpackt, der die bereichsbegrenzte Ressourcenverwaltung (SBRM, zuerst bekannt unter dem dummen / unbeholfenen Namen Initialisierung der Ressourcenerfassung oder RAII) implementiert. Das heißt, dynamische Zuordnungen sollten in automatischen Objekten aufbewahrt werden, die bereinigt werden automatisch hoch!
Ein gutes Beispiel dafür ist std::vector
: Sie können den internen Speicher eines vector
nicht verlieren, da sein Destruktor in jedem Szenario ausgeführt wird, in dem Speicher frei sein sollte, und er wird ihn für Sie freigeben. auto_ptr
ist der erste und einzige intelligente Zeiger, der in der Standardbibliothek verfügbar ist, aber er ist ziemlich schlecht. Besser ist es, shared_ptr
oder viele der anderen populären Smart Pointer zu verwenden, die in Boost und / oder TR1 und / oder C ++ 0x verfügbar sind.
Leistungsmäßig können auf dem Stapel zugewiesene Objekte schnell sehr ausgeführt werden (die Stapelgröße wird pro Funktionsaufruf erhöht, sodass der gesamte erforderliche Speicher von a einfache Bewegung eines Zeigers.) Im Gegensatz dazu erfordert die dynamische Zuweisung im Allgemeinen viel mehr Zeit. Es ist durchaus möglich, schnelle dynamische Zuordnungen mit benutzerdefinierten Zuordnungsschemas zu erhalten, aber selbst die besten werden immer noch langsamer als die Stapelzuweisung sein.
Gelegentlich könnten Sie feststellen, dass Sie zu viel Zeit damit verbringen, Objekte zu kopieren. In diesem Fall kann es sich lohnen, es dynamisch zuzuordnen und lediglich Zeiger zu bewegen. Bitte beachten Sie jedoch, dass ich "finde" gesagt habe. Diese Art von Veränderung findet man durch Profilieren und Messen, ohne zu raten.
Also: Automatische Zuweisung wenn möglich, dynamische Zuweisung bei Bedarf.
Der erste Ansatz erstellt eine lokale Instanz auf dem Stapel, die verschwindet, wenn die aufrufende Funktion beendet wird. Die zweite erstellt eine Instanz, die auf dem Heap bleibt, bis (und wenn) Sie es explizit wieder freigeben. Die Auswahl hängt davon ab, welche Art von Kontrolle und Lebensdauer Sie für Ihr Objekt wünschen.
Als Faustregel gilt: Wenn es ohne new
funktioniert, verwenden Sie nicht new
.
Im Allgemeinen: Sie müssen new
nicht verwenden, wenn Sie beabsichtigen, das Objekt im selben Bereich zu löschen. Wenn das Objekt ziemlich groß ist, können Sie new
verwenden.
Sie können den Unterschied zwischen Heap- und Stack-Speicher untersuchen, wenn Sie die Details kennen möchten.
Stellen Sie sich zunächst die Frage: Ist es sinnvoll, das Objekt zu kopieren, wenn es eine andere Funktion möchte?
Wenn es sinnvoll ist, das Objekt zu kopieren, ist es am besten, alles auf dem Stapel oder als Elementvariable zu erstellen und dann Kopien bei Bedarf einfach weiterzugeben.
Wenn das Kopieren des Objekts nicht sinnvoll ist, müssen Sie new
form verwenden, damit Sie den Zeiger sicher an das Objekt übergeben können. Sie müssen einen Zeiger (oder eine Referenz) verwenden, da es, wie erwähnt, keinen Sinn ergibt, das Objekt zu kopieren.
Ich kenne zwei Ausnahmen:
Wenn Sie wissen, dass das Objekt nach Abschluss der aktuellen Funktion nicht mehr verwendet wird, können Sie das Objekt auf dem Stapel so erstellen, dass es gelöscht wird. Achte nur darauf, dass sich niemand danach an einem Zeiger festhält! (Ich finde selten, dass dies der Fall ist, aber es passiert)
Wenn das Objekt intern von einer anderen Klasse verwendet wird, die selbst nicht kopiert werden soll, können Sie es einfach als Member-Variable einfügen. Da das Objekt, in dem es sich befindet, nicht kopiert wird, und es nur für den internen Gebrauch sicher ist.