heap memory (tsz. heap memories)
A heap memória egy globális memóriaterület, amelyet a program futás közben használhat. Az adatok tárolása itt nem követi a stack memória szigorú LIFO (Last In, First Out) szabályát, hanem a programozó teljes ellenőrzést kap a memóriafoglalás és felszabadítás felett.
A heap memóriát az operációs rendszer kezeli, de a programnak lehetősége van dinamikusan memóriafoglalásra, amikor szükséges.
A heap memória kezeléséhez C++-ban az alábbi operátorokat használjuk:
new
operátor: Memória foglalása a heap-en.delete
operátor: A heap-en foglalt memória felszabadítása.new
és delete
operátorok: Tömbök dinamikus foglalása és felszabadítása.
#include <iostream>
int main() {
int* ptr = new int; // Egy egész számra foglalunk memóriát a heap-en
*ptr = 10; // Értékadás
std::cout << "A dinamikusan foglalt memória értéke: " << *ptr << std::endl;
delete ptr; // Memória felszabadítása
return 0;
}
Ebben a példában: - new int
lefoglal egy memóriaterületet egy egész szám számára. - delete ptr
felszabadítja ezt a memóriaterületet.
Gyakran előfordul, hogy nem egyetlen változót, hanem egy tömböt szeretnénk a heap-en létrehozni.
#include <iostream>
int main() {
int size;
std::cout << "Adja meg a tomb meretet: ";
std::cin >> size;
int* array = new int; // Dinamikus tömb foglalása
for (int i = 0; i < size; i++) {
array = i * 2;
}
std::cout << "Tomb elemei: ";
for (int i = 0; i < size; i++) {
std::cout << array << " ";
}
delete array; // Felszabadítás
return 0;
}
Ebben a példában a program először bekéri a tömb méretét, majd dinamikusan lefoglalja azt a heap-en. A delete
operátorral az egész tömb felszabadításra kerül.
Az osztályokkal való munka során is használnunk kell a dinamikus memóriafoglalást.
#include <iostream>
class Doboz {
public:
int szelesseg, magassag, hossz;
Doboz(int sz, int m, int h) : szelesseg(sz), magassag(m), hossz(h) {}
void mutat() {
std::cout << "Doboz méretei: " << szelesseg << "x" << magassag << "x" << hossz << std::endl;
}
};
int main() {
Doboz* d = new Doboz(10, 20, 30); // Heap-en létrehozott objektum
d->mutat();
delete d; // Objektum felszabadítása
return 0;
}
A new
operátor egy objektum létrehozására is használható. Az objektum konstruktorát és destruktorát a new
és delete
megfelelően hívja meg.
Ha egy program lefoglal memóriát a heap-en, de nem szabadítja fel, az memóriaszivárgáshoz vezethet. Ez hosszabb futásidő esetén növekvő memóriahasználatot eredményez.
void fuggveny() {
int* szam = new int(5);
// Elfelejtettük a delete-et -> Memóriaszivárgás!
}
Mivel a delete
operátor nem hívódik meg, a lefoglalt memória soha nem kerül visszaadásra az operációs rendszernek.
Használjunk okosmutatókat (std::unique_ptr
vagy std::shared_ptr
).
A modern C++ bevezette az okosmutatókat, amelyek automatikusan kezelik a heap memóriát.
std::unique_ptr
– Egyedi tulajdonjog#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> ptr = std::make_unique<int>(10);
std::cout << "Ertek: " << *ptr << std::endl;
return 0;
} // Automatikusan felszabadul
A std::unique_ptr
garantálja, hogy amikor az ptr
kikerül a hatókörből, automatikusan felszabadul a memória.
std::shared_ptr
– Megosztott tulajdonjog#include <iostream>
#include <memory>
void fuggveny(std::shared_ptr<int> p) {
std::cout << "Ertek: " << *p << std::endl;
}
int main() {
std::shared_ptr<int> ptr = std::make_shared<int>(20);
fuggveny(ptr);
return 0;
} // Memória csak akkor szabadul fel, ha az utolsó shared_ptr megszűnik
A std::shared_ptr
lehetővé teszi, hogy több mutató ugyanarra a memóriaterületre mutasson, és az csak akkor szabaduljon fel, ha az utolsó mutató is megszűnik.
✅ Rugalmasság – A program futása közben dinamikusan oszthatunk ki memóriát.
✅ Nagy méretű adatok kezelése – Olyan adatok tárolására is alkalmas, amelyek nem férnének el a stack-en.
✅ Objektumok életciklusának szabályozása – Az objektumokat addig tarthatjuk meg, ameddig szükség van rájuk.
❌ Memóriakezelési hibák – Ha elfelejtjük felszabadítani a memóriát, memóriaszivárgás alakulhat ki.
❌ Többletköltség – A heap memória kezelése lassabb, mert az operációs rendszer allokálja és felszabadítja.
❌ Fragmentáció – Idővel az egymás után lefoglalt és felszabadított memória töredezetté válhat.
A heap memória C++-ban lehetőséget ad a dinamikus memóriafoglalásra és az adatok hosszú távú tárolására. Fontos azonban megfelelően kezelni a memóriát, hogy elkerüljük a memóriaszivárgást és a fragmentációt. Az okosmutatók (std::unique_ptr
, std::shared_ptr
) használata biztonságosabb megoldást nyújt, ezért modern C++ kódban ajánlott őket alkalmazni.