Im Gegenteil, Sie sollten immer Stapelzuordnungen bevorzugen, sofern Sie als Faustregel niemals Neu / Löschen in Ihrem Benutzercode haben sollten.
Wie Sie sagen, wenn die Variable auf dem Stapel deklariert wird, wird ihr Destruktor automatisch aufgerufen, wenn sie den Gültigkeitsbereich verlässt. Dies ist Ihr Hauptwerkzeug zur Verfolgung der Ressourcenlebensdauer und zur Vermeidung von Lecks.
Wenn Sie also eine Ressource zuweisen müssen, egal ob es sich um Speicher (durch Aufrufen von new), Dateihandles, Sockets oder etwas anderes handelt, schließen Sie sie im Allgemeinen in eine Klasse ein, in der der Konstruktor die Ressource abruft und der Destruktor sie freigibt. Anschließend können Sie ein Objekt dieses Typs auf dem Stapel erstellen, und Sie können sicher sein, dass Ihre Ressource freigegeben wird, wenn sie den Gültigkeitsbereich verlässt. Auf diese Weise müssen Sie Ihre neuen / gelöschten Paare nicht überall verfolgen, um Speicherlecks zu vermeiden.
Der gebräuchlichste Name für diese Redewendung ist RAII
Schauen Sie sich auch Smart-Pointer-Klassen an, mit denen die resultierenden Zeiger in den seltenen Fällen umbrochen werden, in denen Sie außerhalb eines dedizierten RAII-Objekts etwas mit new zuweisen müssen. Sie übergeben den Zeiger stattdessen an einen intelligenten Zeiger, der dann seine Lebensdauer beispielsweise durch Referenzzählung verfolgt und den Destruktor aufruft, wenn die letzte Referenz den Gültigkeitsbereich verlässt. Die Standardbibliothek verfügt std::unique_ptr
über eine einfache bereichsbasierte Verwaltung, std::shared_ptr
die Referenzzählungen zur Implementierung von gemeinsamem Besitz durchführt.
Viele Tutorials demonstrieren die Objektinstanziierung mithilfe eines Snippets wie ...
Sie haben also festgestellt, dass die meisten Tutorials scheiße sind. ;) In den meisten Tutorials lernen Sie miese C ++ - Praktiken, einschließlich des Aufrufs von new / delete, um Variablen zu erstellen, wenn dies nicht erforderlich ist, und der Schwierigkeit, die Lebensdauer Ihrer Zuordnungen zu verfolgen.
Obwohl es von Vorteil sein kann, Dinge auf dem Stapel zu haben, was die Zuweisung und das automatische Freigeben betrifft, hat dies einige Nachteile.
Möglicherweise möchten Sie keine großen Objekte auf dem Stapel zuweisen.
Dynamischer Versand! Betrachten Sie diesen Code:
Dies wird "B" drucken. Nun wollen wir sehen, was bei der Verwendung von Stack passiert:
Dadurch wird "A" gedruckt, was für diejenigen, die mit Java oder anderen objektorientierten Sprachen vertraut sind, möglicherweise nicht intuitiv ist. Der Grund ist, dass Sie keinen Zeiger mehr auf eine Instanz von haben
B
. Stattdessen wird eine Instanz vonB
erstellt und in einea
Variable vom Typ kopiertA
.Einige Dinge können unbeabsichtigt passieren, insbesondere wenn Sie mit C ++ noch nicht vertraut sind. In C haben Sie Ihre Zeiger und das wars. Sie wissen, wie man sie benutzt und sie tun IMMER das Gleiche. In C ++ ist dies nicht der Fall. Man stelle sich vor , was passiert, wenn Sie ein in diesem Beispiel als Argument für eine Methode - die Dinge komplizierter und es macht einen großen Unterschied machen , wenn
a
der Typ istA
oderA*
oder auchA&
(Call-by-reference). Viele Kombinationen sind möglich und verhalten sich alle unterschiedlich.quelle
Nun, der Grund für die Verwendung des Zeigers wäre genau der gleiche wie der Grund für die Verwendung von Zeigern in C, die mit malloc zugewiesen wurden: Wenn Sie möchten, dass Ihr Objekt länger als Ihre Variable lebt!
Es wird sogar dringend empfohlen, den neuen Operator NICHT zu verwenden, wenn Sie dies vermeiden können. Vor allem, wenn Sie Ausnahmen verwenden. Im Allgemeinen ist es viel sicherer, den Compiler Ihre Objekte freigeben zu lassen.
quelle
Ich habe dieses Anti-Muster von Leuten gesehen, die die & Adresse des Betreibers nicht ganz verstehen. Wenn sie eine Funktion mit einem Zeiger aufrufen müssen, ordnen sie sie immer dem Heap zu, damit sie einen Zeiger erhalten.
quelle
Behandeln Sie Haufen als eine sehr wichtige Immobilie und verwenden Sie sie sehr vernünftig. Die grundlegende Faustregel lautet, wann immer möglich Stapel zu verwenden und Heap zu verwenden, wann immer es keinen anderen Weg gibt. Durch Zuweisen der Objekte auf dem Stapel können Sie viele Vorteile erzielen, wie z.
(1). In Ausnahmefällen müssen Sie sich keine Gedanken über das Abwickeln des Stapels machen
(2). Sie müssen sich keine Gedanken über die Speicherfragmentierung machen, die durch die Zuweisung von mehr Speicherplatz als von Ihrem Heap-Manager erforderlich verursacht wird.
quelle
Der einzige Grund, über den ich mir Sorgen machen würde, ist, dass Dog jetzt auf dem Stapel und nicht auf dem Haufen zugewiesen ist. Wenn der Hund also Megabyte groß ist, liegt möglicherweise ein Problem vor:
Wenn Sie die neue / gelöschte Route wählen müssen, seien Sie vorsichtig mit Ausnahmen. Aus diesem Grund sollten Sie auto_ptr oder einen der Boost-Smart-Zeigertypen verwenden, um die Objektlebensdauer zu verwalten.
quelle
Es gibt keinen Grund zu neu (auf dem Heap), wenn Sie auf dem Stapel zuordnen können (es sei denn, Sie haben aus irgendeinem Grund einen kleinen Stapel und möchten den Heap verwenden.
Möglicherweise möchten Sie einen shared_ptr (oder eine seiner Varianten) aus der Standardbibliothek verwenden, wenn Sie ihn auf dem Heap zuweisen möchten. Damit wird das Löschen für Sie erledigt, sobald alle Verweise auf shared_ptr nicht mehr vorhanden sind.
quelle
Es gibt einen zusätzlichen Grund, den noch niemand erwähnt hat, warum Sie Ihr Objekt möglicherweise dynamisch erstellen. Mit dynamischen, Heap-basierten Objekten können Sie Polymorphismus nutzen .
quelle
Ich hatte das gleiche Problem in Visual Studio. Sie müssen verwenden:
yourClass-> classMethod ();
eher, als:
yourClass.classMethod ();
quelle