delete
Kiejtés
- IPA: /dɪˈliːt/
Ige
delete (alapjelen, egyes szám harmadik személy deletes, folyamatos melléknévi igenév deleting, második és harmadik alakja deleted)
A delete
kulcsszó C++-ban a dinamikusan foglalt memória felszabadítására szolgál. Amikor a new
operátorral memóriát foglalunk a heapen, azt kézzel kell felszabadítani, különben memóriaszivárgás léphet fel.
1. Miért van szükség a delete
kulcsszóra?
A stack memóriában lévő változók automatikusan felszabadulnak, amikor a függvény befejeződik:
void fuggveny() {
int x = 5; // Automatikusan törlődik a függvény végeztével
}
Ezzel szemben a heap memóriában lévő adatok nem szabadulnak fel automatikusan:
int* p = new int(10); // Dinamikus memóriafoglalás
// Ha itt nem használunk `delete p;`, memóriaszivárgás történik!
Ha nem használjuk a delete
-et, akkor a memória nem kerül vissza az operációs rendszerhez, ami idővel memóriahiányhoz vezethet.
2. Egyszerű delete
használat
A delete
operátort egyedi objektumok felszabadítására használjuk.
Példa: Dinamikus memória felszabadítása
#include <iostream>
using namespace std;
int main() {
int* ptr = new int(42); // Egy `int` foglalása a heapen
cout << "Érték: " << *ptr << endl;
delete ptr; // Felszabadítjuk a memóriát
ptr = nullptr; // Jó gyakorlat: érvénytelenítjük a mutatót
return 0;
}
Fontos:
- A delete ptr;
felszabadítja az int
-hez tartozó memóriát. - A ptr = nullptr;
megakadályozza, hogy a mutató egy felszabadított területre mutasson (dangling pointer elkerülése).
3. delete[]
használata tömböknél
Ha egy dinamikus tömböt (new[]
) foglalunk, akkor delete[]
-et kell használni.
Helytelen használat (delete
tömb esetén)
int* tomb = new int[5];
delete tomb; // HIBA! Csak az első elem szabadul fel
Ez memóriaszivárgást okozhat, mert a tömb többi eleme nem kerül felszabadításra!
Helyes használat (delete[]
)
int* tomb = new int[5];
delete[] tomb; // Helyesen felszabadítja a teljes tömböt
tomb = nullptr;
Miért van külön delete
és delete[]
?
- A delete
egyetlen objektumot töröl. - A delete[]
biztosítja, hogy a teljes tömb memóriája felszabaduljon.
4. Osztálypéldányok és delete
Amikor egy osztályt dinamikusan hozunk létre, a delete
automatikusan meghívja az osztály destruktorát (~ClassName()
).
Példa osztálypéldányok törlésére
#include <iostream>
using namespace std;
class Ember {
public:
string nev;
Ember(string n) {
nev = n;
cout << nev << " létrehozva!" << endl;
}
~Ember() {
cout << nev << " törölve!" << endl;
}
};
int main() {
Ember* p = new Ember("Anna");
delete p; // A destruktor automatikusan meghívódik
return 0;
}
Kimenet:
Anna létrehozva! Anna törölve!
Mi történik? - A new
létrehoz egy Ember
objektumot a heapen. - A delete p;
felszabadítja a memóriát és meghívja a destruktort.
5. Tömbök és osztálypéldányok (delete[]
)
Ha egy osztálytömböt dinamikusan foglalunk, a delete[]
hívja meg az összes objektum destruktorát.
Példa: Osztálypéldányok tömbjének felszabadítása
#include <iostream>
using namespace std;
class Ember {
public:
Ember() { cout << "Létrejött egy ember!" << endl; }
~Ember() { cout << "Egy ember törölve!" << endl; }
};
int main() {
Ember* emberek = new Ember[3]; // Három objektum a heapen
delete[] emberek; // Minden objektum destruktora meghívódik
return 0;
}
Kimenet:
Létrejött egy ember! Létrejött egy ember! Létrejött egy ember! Egy ember törölve! Egy ember törölve! Egy ember törölve!
6. delete
és virtuális destruktorok
Ha egy osztályban öröklődés van, és az objektumot az alaposztály mutatóján keresztül töröljük, akkor a destruktor legyen virtuális!
Példa hibás törlésre (nincs virtual
destruktor)
class Alap {
public:
~Alap() { cout << "Alap destruktor" << endl; }
};
class Szarmaztatott : public Alap {
public:
~Szarmaztatott() { cout << "Származtatott destruktor" << endl; }
};
int main() {
Alap* obj = new Szarmaztatott();
delete obj; // Csak az Alap destruktora hívódik meg!
return 0;
}
Kimenet:
Alap destruktor
Mi a baj? - Csak az alaposztály destruktora fut le, így a leszármazott objektum memóriaszivárgást okozhat.
Megoldás: Virtuális destruktor
class Alap {
public:
virtual ~Alap() { cout << "Alap destruktor" << endl; }
};
class Szarmaztatott : public Alap {
public:
~Szarmaztatott() { cout << "Származtatott destruktor" << endl; }
};
int main() {
Alap* obj = new Szarmaztatott();
delete obj; // Most mindkét destruktor lefut!
return 0;
}
Kimenet:
Származtatott destruktor Alap destruktor
Megoldás:
A virtuális destruktor (virtual ~Alap()
) biztosítja, hogy az összes leszármazott osztály destruktora helyesen lefusson.
7. Gyakori hibák és megoldások
Hiba | Probléma | Megoldás |
---|---|---|
delete egy tömbre
|
Csak az első elem szabadul fel | Használj delete[] -et
|
delete[] egy objektumra
|
Undefined behavior | Használj delete -et
|
delete -et elfelejtjük
|
Memóriaszivárgás | Minden new után legyen delete
|
Dupla delete (delete ptr kétszer)
|
Double delete hiba | Használj ptr = nullptr; után
|
Öröklött osztály destruktora nem hívódik meg | Memóriaszivárgás | Használj virtuális destruktort |
8. Összegzés
delete
egyetlen dinamikusan foglalt objektumot töröl.delete[]
dinamikus tömböket töröl.- Mindig használd a
delete
után anullptr
-t, hogy elkerüld a dangling pointereket. - Virtuális destruktorok szükségesek, ha az objektumot polimorf módon törlöd (
Alap* p = new Szarmaztatott();
).
A helyes delete
használat kulcsfontosságú a memóriakezelés és a stabil C++ programok szempontjából!