2016-04-15 13 views
7

Ich frage mich, wann sollte ich eine Klasse auf dem Stapel in C++ zuweisen? Ich habe einen starken Hintergrund in Java und in Java werden alle Klassen auf dem Heap mit dem Schlüsselwort new zugewiesen. In C++ kann ich zwischen Stapel- und Heap-Zuweisung wählen, aber jetzt, da Smartpointer eingeführt werden, ist es sinnvoller, alles zuzuordnen, was den Besitz nicht mit std::unique_ptr überträgt.C++ - Stapel vs Heap-Zuweisung

Ich kann nicht wirklich an Fälle denken, in denen es notwendig oder besser wäre, Stack-Zuweisung zu verwenden. Vielleicht für eine Art von Optimierung in eingebetteten Systemen?

+2

Nur ein FYI ein 'std :: unique_ptr' ist ein" stack "-basiertes Objekt. BTW nennen wir dann automatische und dynamische Objekte, da C++ kein Stack- oder Heap-Konzept hat. IMHO Sie wollen automatische Objekte wann immer möglich verwenden, – NathanOliver

+9

Sie verwenden normalerweise das gegenteilige Prinzip: Wenn dynamische Zuordnung nicht erforderlich ist, tun Sie es nicht. Die dynamische Zuweisung ist standardmäßig "vorzeitige Pessimierung". – molbdnilo

Antwort

14

Verwendung automatische (stack), wann immer die Zuweisung Funktionsumfang - oder der Umfang eines Steuerblockes, wie ein for, while, if usw. innerhalb der Funktion - eine gute Übereinstimmung für die Lebensdauer ist das Objekt braucht. Auf diese Weise werden, wenn das Objekt Ressourcen besitzt oder steuert, wie dynamisch zugeordneter Speicher, Dateizugriffsnummern usw., diese während des Destruktoraufrufs freigegeben, wenn dieser Bereich verlassen wird. (Nicht zu irgendeiner unvorhersehbaren späteren Zeit, wenn ein Müllsammler aufläuft).

Nur new verwenden, wenn es gibt einen klaren Bedarf, wie zum Beispiel:

  • das Objekt benötigt länger als der Funktionsumfang zu leben,

  • auszuhändigen Eigentum an einen anderen Code

  • um einen Container mit Zeigern auf Basisklassen zu haben, den Sie dann polymorph verarbeiten können (dh Verwenden von virtuellem Versand zu abgeleiteten Klassenfunktionsimplementierungen) oder

  • eine besonders große Zuteilung, die viel von dem Stapel auffressen würde (O/Prozess eine Grenze „ausgehandelt“ haben wird, in der Regel in 1-8 + Megabyte-Bereich)

    • wenn dies der einzige ist Wenn Sie die dynamische Zuordnung verwenden und die Lebensdauer des Objekts an einen Bereich in Ihrer Funktion gebunden ist, sollten Sie einen lokalen std::unique_ptr<> verwenden, um den dynamischen Speicher zu verwalten und sicherzustellen, dass er unabhängig vom Verlassen des Bereichs freigegeben wird: von return, throw, break usw .. (Sie können auch ein std::unique_ptr<> Datenelement in einem class/struct verwenden, um Speicher zu verwalten, der das Objekt besitzt.)

Mathieu Van Nevel kommentiert unter etwa C++ 11 bewegen Semantik - die Bedeutung ist, dass wenn Sie ein kleines Management-Objekt auf dem Stack, der eine große Menge an dynamisch zugewiesenen (Heap) Speicher, bewegen steuert Semantik gewährt zusätzliche Garantien und feinkörnige Kontrolle darüber, wann das Verwaltungsobjekt seine Ressourcen an ein anderes Verwaltungsobjekt übergibt, das anderem Code gehört (oft der Aufrufer, möglicherweise aber auch ein anderer Container/ein anderes Register von Objekten). Diese Übergabe kann verhindern, dass Daten auf dem Heap noch für einen Moment kopiert/dupliziert werden. elision und return-value-optimization oft erlauben nominal automatisch/stack-gehostete Variablen direkt in einigen Speicher erstellt werden sie schließlich zugeordnet/zurückgegeben werden, anstatt später dort kopiert.

+0

das ist eine gute Zusammenfassung. Kürzlich habe ich Code überarbeitet, der ein Array sehr großer Objekte in den Stapel brachte. Wenn Sie nicht vorsichtig sind, können Sie den Stack-Speicherplatz in einem größeren Programm oder einem mit tiefer Rekursion auslassen. –

+0

Einige Details über C++ 11 move semantic, und die Antwort wird perfekt sein, denke ich: upvote –

+0

Gute Zusammenfassung, wenn Sie hinzufügen, wann sollte ich std :: unique_ptr anstelle von Stack-Zuweisung verwenden, werde ich Ihnen die Antwort Tick geben. – KillerZefi

1

In großen Codebasen verwenden wir die Stapelzuordnung für einfache Strukturobjekte, während für komplexere Klassen (die Polymorphie, Speicherbesitz usw. beinhalten) immer die dynamische Zuweisung verwendet wird.