Stack vs Heap C++
Ich hatte gerade eine kurze Frage, wie stack-Variablen versus heap-Variablen arbeiten. Wie ich es verstehe, stack-Variablen sind Variablen, die nach Funktionen, werden gelöscht, und heap-Variablen sind persistent. Aber was mich wirklich verwirrt, ist die Art der Allokation der heap-Variablen innerhalb von Funktionen:
int MyObject::addObject(const char* a){
MyObject newObject(a);
return 0;
}
Sagen, dass ich einen Konstruktor für MyObject
ist newObject(const char * a)
. Dann in dieser Funktion, wenn Sie aufgerufen wird, nach der Rückkehr hat der neu errichteten newObject
gelöscht zu bekommen? Wenn ja, wie können Sie reservieren in den heap innerhalb einer Funktion dann? Wenn nicht, wie können Sie bereinigen Ihre Speicher später?
Außerdem, was genau ist die Rolle von einem Destruktor und Wann wird es aufgerufen?
- Haben Sie sich überlegt mit std::string statt char* ? Werfen C Speicher-management in den mix neigt zu befuddle, Ihre MyObject-Klasse muss nun entscheiden, wie besitzt die Speicher für den Zeiger und wahrscheinlich braucht, um kopieren Sie die Zeichenfolge und einen Destruktor, um es wieder freigeben. Dies nicht zu tun, ist eine sehr wahrscheinliche Pfad zu Versagen.
- Sie sollten nicht einmal denken, "stack" und "heap". Wenn Sie ein Auto fahren, werden Sie in der Regel nicht über die Zylinder-Zyklus prasselt, tun Sie? Die Dinge zu verstehen, die in C++ sind storage-Klassen und Objekt-Lebensdauer: automatisch (scoped), dynamisch (manuell), statisch (global).
- Wenn Sie mit C oder C++, würde Sie bestreiten, dass es gut zu wissen, den Unterschied zwischen den beiden? Ich denke, das ist, was OP ist immer hier.
- Ich würde sagen, es ist verwirrend und irreführend, auch nur zu erwägen die beiden. Diese sind eine Implementierung detail, dass Sie nachdenken können, an einem regnerischen Sonntag über Kaffee, aber für die Zwecke der das Verständnis von C++ sind Sie unnötige Unordnung und Lärm... besonders, wenn du neu bist und noch so viel mehr wichtige Dinge zu lernen 🙂
- Was für ein Zufall, es ist Sonntag und es regnet. Kaffee brauen.
- SB, Stimme überhaupt nicht zu. Wissen Sie, dass die Standard-stack-Größe auf 32-bit-Windows-1 MB groß ist? Wenn der Anfänger weiß das nicht, (s)er kann denken, cool, werde ich nutzen stack die ganze Zeit — aber Sie sollten wirklich nicht tun.
- Ich würde sagen, dass ein Algorithmus verwendet, der viel stack-Größe, die vielleicht andere Probleme haben. Sicher gibt es Situationen, wo Sie brauchen nur einen lokalen Speicherblock (in diesem Fall sollten Sie die drop-in ersetzen
std::unique_ptr<Foo[]>
), aber das dürfte eine seltene Ausnahme. - Ich auch nicht Zustimmen. Diese sind nicht in der Umsetzung details, dies sind die Konzepte, die Sie haben zu verstehen, für die gleichen Gründe, dass Klassen und Objekte sind Konzepte, die in einer OOP-Sprache, und Sie sollten verstehen, diejenigen, die als gut. Wenn Sie nicht wissen, wo Ihre Gegenstände sind und das Leben derer, die Sie nicht in der Lage sein, zu schreiben, effizienten c++ - code. Nicht in den aktuellen Zustand der Sprache ist mindestens. Es gibt nur so viel Sie bekommen können entfernt, indem nur an der Oberfläche kratzen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einen Konstruktor für die Klasse
MyObject
istMyObject()
, nichtnewObject()
. In deinem BeispielnewObject
ist der name der Variablen, nicht der Konstruktor.Zu allokieren auf dem heap innerhalb einer Funktion, die Sie aufrufen müssen, die
new
Betreiber:Code:
erstellt eine automatische Ablage (stapeln)
MyObject
genanntnewObject
lebt, bis der Zweck, für den er erklärt wurde, in enden - d.h. schließen}
.Reinigen Speicher der Klasse zugeordnet, die mit
new
odernew[]
(odermalloc
), und es besitzt. Es wird aufgerufen, wenn das Objekt außerhalb des Gültigkeitsbereichs für die automatische Objekte, oder wenn Sie explizit aufrufendelete
für dynamische Objekte.new
Stack-Speicher ist, was Sie sagte, aber um genauer zu sein, es ist lokalen Speicher, um den aktuellen Bereich. Beachten Sie, dass je nachdem, in welchem Bereich du redest, dieser Speicher könnte global sein, oder es könnte sein, lokal in einer Funktion oder Klasse. Diese bereinigt werden, sobald Sie gegangen sind out-of-scope.
Heap-Speicher in zugewiesen, über die
new
Betreiber.Diese bleiben im Speicher bewahrt, auch nachdem alle Zeiger zeigen auf den Speicher gegangen sind, aus der Umfang. Sie muss ausdrücklich die Veröffentlichung dieser Speicher selbst in C++ über
delete
. Geschieht dies nicht, wird das Ergebnis in einem Speicher-Leck, es sei denn, intelligente Zeiger verwendet werden.Andere Sache zu beachten, die folgenden Beispiel-code:
den Zeiger selbst, in der bar, wird auf dem Stapel erzeugt. Die Daten werden jedoch darauf hingewiesen, durch die bar. *bar -- ja, das Sternchen macht den Unterschied hier. Es bekommt die Daten, wies auf die durch den Zeiger-ist auf dem heap. Wenn foo zurück, die bar außerhalb des Bereichs. Hätte ich nicht angerufen löschen, ich hätte Sie verloren den Zugang zu *bar und es hätten ein memory leak.
Für die zweite Frage, die Rolle des dtor bereinigen Sie das Objekt, das Sie konstruiert haben. Einer ist standardmäßig für Sie, aber es gibt Zeiten, wenn Sie brauchen, um Ihre eigenen schreiben. Zum Beispiel, wenn Ihre Klasse hat raw-Pointer in ihm ist, müssen Sie explizit freigeben mit delete in der dtor. Es wird aufgerufen, wenn das Objekt außerhalb des Gültigkeitsbereichs für stack-Speicher, und beim löschen wird aufgerufen, für heap-Speicher.
Dieser code weist newObject auf den stack. Es ist konstruiert (MyObject-Konstruktor aufgerufen wird, die auf einen chunk-stack-Speicher) bei der Eingabe der Funktion. Es ist zerstört (MyObject Destruktor aufgerufen für diese Instanz), wenn die Funktion zurückkehrt, kurz bevor der chunk-Speicher tauchte aus dem Stapel.
Dieser code weist einem Objekt auf dem heap. Der Konstruktor aufgerufen wird, wird durch den neuen Betreiber, nachdem es zugeordnet einige heap-Speicher. Der Speicher ist nicht freigegeben, und der Destruktor nicht aufgerufen, bis Sie ausdrücklich sagen, Sie fertig sind mit es mit dem delete-Schlüsselwort.
Diese können überall, die Sie wollen in Ihrem Programm.
foo
? Wo lebt er? Wie wird es verwaltet?Der stack ist ein Bereich, der verwendet wird in Funktions-und Methodenaufrufe. Es ist im Grunde verwendet, um Parameter zu hinterlegen und die Funktion lokaler Daten (unter anderem involviert in den Prozess der Aufruf einer Funktion). Der stack ist ein LIFO-Art der Daten-Struktur, was bedeutet, dass die Letzte Sache, die Sie stellen, ist die erste, die Sie von ihm bekommen.
Den Haufen auf der anderen Seite ist ein kostenloser Shop, damit meine ich, dass man alle Werte aus dem heap egal, die Bestellung es wurde dort - diese Unterscheidung ist wichtig.
In C++ , jedes mal, wenn Sie rufen
new
das Objekt auf dem Heap erstellt und ein Zeiger auf dieses Objekt zurückgegeben, Sie können dann diesen Zeiger zum Zugriff auf Ihr Objekt. Das gilt sowohl für komplexe Objekte, wie Objekte von Klassen, die Sie oder jemand anderes erstellt hat und die eingebauten Datentypen, wie int, char, double etc... Es ist nichts Magisches mit neuen, im Kern es ruft einfachmalloc
oder einige der Geschmack, abhängig von der Plattform und ruft dann den Konstruktor für das Objekt. Sie haben sich daran zu erinnern zu nennendelete
(oderdelete []p_array_of_object_pointers
) für jedes Objekt erstellt, mitnew
.Destruktor ist nichts anderes als eine Funktion, die die Sprache fordert das Objekt, wenn Sie eine
delete my_object_pointer
im code. Der Destruktor gibt Ihnen eine chance zu tun, etwas Ordnung in den code. In Sprachen wie C++, wo Sie verwalten Ihre eigenen Ressourcen, Sie würden in der Regel verwenden Sie es zu nennendelete
oderfree
auf andere Objekte, die Sie zugewiesen haben, auf dem heap oder schließen, Datei-handles, die Sie erstellt haben, mit fopen oder so...Beiden dieses keywords innerhalb oder außerhalb von Funktionen und Methoden, es spielt keine Rolle, wo Sie Sie nennen, Sie werden immer das arbeiten mit dem heap. Alles, was Sie erschaffen, ohne die Verwendung von
new
wird am Ende in einem anderen Ort, entweder den statischen Bereich der ausführbaren Datei oder der Stapel, je nachdem, wie und wo es angelegt wird.Jedes mal, wenn Sie erstellen ein Objekt innerhalb einer Methode oder Funktion mit der folgenden syntax
MyClassType myObject(contructor, arguments);
und ohne den Einsatz vonnew
Sie schaffen es auf den stack (es sei denn, Sie deklarieren Sie als statisch, wenn es endet in diesem statischen Bereich, den ich oben erwähnt).Hoffe, das hilft.
heap-Zuweisungen sind fertig mit der
new
StichwortC++ besitzt keine garbage collection, heap-Zuweisungen sind nicht automatisch befreit
können Sie kostenlos mit der
delete
StichwortSie benötigen, um einen Zeiger für, die, beispielsweise durch Rückgabe aus der Funktion, oder durch Zuweisung an eine Globale variable
Destruktoren werden aufgerufen, auf
delete
sind und verwendet werden, um Ressourcen freizugeben, beispielsweise Netzwerk-socketsso, dass der code wäre zum Beispiel
return new MyObject("foo");
Reservieren von Speicher im stack in deinem Beispiel. Es ist eine automatische variable, und es würde gelöscht werden, dann wieder passiert.
Wenn Sie
new
Stichwort Sie müssen korrekte FreigabeHow to allocate heap: verwenden Sie
new
StichwortWie freigeben von heap: verwenden Sie
delete
Stichwort.Zu vermeiden, Programm-Abstürzen und Speicher-Lecks jeder
new
muss seinedelete
Gegenstück für das angegebene Objekt und Typ.Destruktor wird aufgerufen, wenn das Objekt gelöscht wird, unabhängig davon, wo es gespeichert wurde(heap, stack, ...)
Und hier sind weitere spezifische Informationen über das Gedächtnis: Was und wo sind die stack und heap?
Dynamisch reservierten Instanzen von Objekten, wenn:
1) Der tatsächliche Typ des Objekts, wird zur Kompilierzeit nicht bekannt
2) Wenn die Anzahl der Objekte, die Sie erstellen möchten, ist es zur Kompilierzeit nicht bekannt
3) Wenn der (compiler generiert) die Verwaltung des Lebenszyklus Ihrer Objekte nicht Ihren Bedürfnissen.
Jedes Objekt erstellt mit dem new-operator, freigegeben werden soll, mit dem delete-operator zu einem bestimmten Zeitpunkt. Wenn Sie nicht, Sie haben Speicherlecks, und wenn Sie ab auf die Nebenwirkungen der Objekte Destruktor, Sie erhalten nicht diese Nebenwirkungen und das Programm kann nicht tun, was es ist, das gewünschte zu tun.
Wenn ein Objekt erstellt wird als stack-variable, der compiler fügt code, um die Objekte Destruktor, wenn das Objekt außerhalb des Gültigkeitsbereichs. Wie weiß der compiler wissen, was Destruktor aufrufen? Der Typ des Objekts zur Kompilierzeit bekannt ist, so gibt es nur eine Möglichkeit, nur einen destructor zu nennen.
Wenn Sie 'löschen' zu zerstören, ein Objekt kann der compiler nicht in der Lage sein, zu erkennen, welcher Destruktor zu verwenden. Das Objekt des Typs "basic", dann wird der Destruktor von 'basic::~basic()' aufgerufen wird.
Nicht der compiler wissen, dass die tatsächlichen Typ des Objekts ist nicht 'basic', aber 'abgeleitet'. Wenn doch, erklären Sie den Destruktor von "basic" zu sein virtuellen, der compiler code ein, der erkundigt sich bei den Objekten der virtuellen Methode-Tabelle, und der Anruf wird umgeleitet, um die richtige Destruktor (in diesem Fall wird der Destruktor, die sich auf Objekt vom Typ 'abgeleitet').
Wenn Sie sind besorgt über dieses problem, und wenn Sie können, stellen Sie den Destruktor der 'virtuellen'.