Stack- vs. Heap-Speicher
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 12 von 104.
C++-Programme verwenden zwei wichtige Speicherbereiche: den stack und den heap. Zu verstehen, wo deine Objekte leben, ist entscheidend, um effizienten und fehlerfreien Code zu schreiben.
Der Stack ist ein schneller, automatisch verwalteter Speicher. Variablen, die innerhalb von Funktionen deklariert werden, leben hier und werden automatisch zerstört, wenn sie ihren Gültigkeitsbereich verlassen.
void example() {
int x = 10; // Stack-Allokation
Player player; // Stack-Allokation - wird automatisch zerstört
} // x und player werden hier zerstörtDer Heap ist ein größerer, aber langsamerer Speicher, den du manuell verwaltest. Objekte auf dem Heap bleiben bestehen, bis du sie ausdrücklich löschst.
void example() {
Player* player = new Player(); // Heap-Allokation
// player existiert, bis er gelöscht wird
delete player; // Manuelle Bereinigung erforderlich
}Wichtige Unterschiede:
| Stack | Heap |
|---|---|
| Schnelle Allokation | Langsamere Allokation |
| Begrenzte Größe | Große Kapazität |
| Automatische Bereinigung | Manuelle Bereinigung erforderlich |
| Objekte fester Größe | Objekte variabler Größe |
Verwende die Stack-Allokation für kleine Objekte mit kurzer Lebensdauer. Verwende die Heap-Allokation, wenn Objekte ihren Gültigkeitsbereich überdauern müssen oder wenn ihre Größe zur Laufzeit bestimmt wird.
Wenn du vergisst, den Heap-Speicher zu löschen, verursacht das Speicherlecks, eine häufige Fehlerquelle in C++-Programmen.
Aufgabe
EinfachSehen wir uns den Unterschied zwischen Stack- und Heap-Speicher an, indem wir eine einfache Counter-Klasse erstellen, die verfolgt, wie Objekte erstellt und zerstört werden.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
Counter.h: Definiere eineCounter-Klasse mit einem privatenname-Attribut (String). Füge einen Konstruktor hinzu, der einen Namen entgegennimmt und"Creating: <name>"ausgibt, sowie einen Destruktor, der"Destroying: <name>"ausgibt. Füge einegetName()-Methode hinzu, die den Namen des Counters zurückgibt.main.cpp: Demonstriere sowohl die Stack- als auch die Heap-Allokation. Lies einen Namen von der Eingabe ein und:- Erstelle einen Stack-allokierten
Countermit diesem Namen - Erstelle einen Heap-allokierten
Countermit dem Namen"HeapCounter" - Gib beide Counter-Namen im Format
"Stack: <name>"und"Heap: <name>"aus - Lösche den Heap-allokierten Counter, um ein Speicherleck zu verhindern
- Erstelle einen Stack-allokierten
Beobachte, wie die Meldungen des Konstruktors und Destruktors in unterschiedlicher Reihenfolge erscheinen, abhängig davon, wann du die einzelnen Objekte erstellst und löschst. Das Stack-Objekt wird automatisch zerstört, wenn main() endet, während das Heap-Objekt explizit gelöscht werden muss.
Binde deine Headerdatei in main.cpp mit #include "Counter.h" ein.
Probier es selbst
#include <iostream>
#include <string>
#include "Counter.h"
using namespace std;
int main() {
// Namen von der Eingabe lesen
string inputName;
cin >> inputName;
// TODO: Erstelle einen stack-allokierten Counter unter Verwendung von inputName
// TODO: Erstelle einen heap-allokierten Counter mit dem Namen "HeapCounter"
// TODO: Print stack counter name in format "Stack: <name>"
// TODO: Gib den Namen des Heap-Counters im Format "Heap: <name>" aus
// TODO: Lösche den heap-allokierten Counter, um ein Speicherleck zu verhindern
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamespaces & GültigkeitsbereichEinführung in OOP mit C++Klassen vs. ObjekteDer „this“-ZeigerMethoden (Member-Funktionen)Attribute (Datenmember)Grundlagen zu Ctors & DtorsRückblick – Einfacher Taschenrechner4Klassenattribute
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen und -KlassenZusammenfassung – Bankkontoverwaltung7Vererbung
Grundlagen der VererbungZugriffsebenen bei der VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick – Mitarbeiterhierarchie2Speicherverwaltung
Stack- vs. Heap-SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Intelligente Zeiger in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsbezeichner in C++Zugriffsbezeichner im DetailInformationsverbergungStruct vs. KlasseVerschachtelte und innere KlassenWiederholung – Studierendenverwaltungssystem8Polymorphie
Polymorphie zur Compilezeit vs. LaufzeitFunktionsüberladungVirtuelle Funktionen erneut betrachtetRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIRückblick – Shape-Calculator3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorMove-KonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktor im DetailDrei-/Fünf-/Null-RegelZusammenfassung – String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladung der Operatoren [] und ()TypkonvertierungsoperatorenWiederholung – Matrix-Klasse9Templates
FunktionstemplatesKlassen-TemplatesTemplate-SpezialisierungVariadische TemplatesGrundlagen zu SFINAE und Type TraitsRückblick – Generischer ContainerÜbe selbstständig: Online-C++-Compiler