smart pointer (tsz. smart pointers)
Az okosmutatók (smart pointers) olyan automatizált memória kezelő eszközök, amelyek a C++ standard könyvtárban (STL) találhatók. Segítenek elkerülni a memóriaszivárgást és a vad mutatókat, mivel automatikusan felszabadítják az általuk foglalt memóriát, amikor az már nem szükséges.
C++ manuális memória kezelésében (new
és delete
) könnyen elkövethető hibák:
❌ Memóriaszivárgás, ha elfelejtjük felszabadítani a memóriát.
❌ Vad mutatók, ha egy felszabadított memóriaterületre próbálunk hivatkozni.
❌ Dupla törlés, ha egy mutatót kétszer törlünk.
Az okosmutatók ezeket a problémákat oldják meg, mert automatikusan felszabadítják a memóriát, amikor már nem használjuk őket.
C++11 és újabb szabványok három fő okosmutató típust biztosítanak:
Okosmutató | Leírás |
---|---|
std::unique_ptr
|
Egyedi tulajdonú mutató (csak egy mutató birtokolhatja az objektumot). |
std::shared_ptr
|
Megosztott mutató (több mutató is birtokolhatja ugyanazt az objektumot). |
std::weak_ptr
|
Gyenge mutató (nem növeli a referencia számlálót, elkerüli a ciklikus referenciákat). |
std::unique_ptr
– Egyedüli tulajdonú mutatóA std::unique_ptr
olyan okosmutató, amely egyedi tulajdonjogot biztosít az objektum felett. Ez azt jelenti, hogy csak egyetlen unique_ptr
birtokolhat egy adott objektumot.
✅ Automatikusan törli az objektumot, amikor elhagyja a hatókört.
✅ Biztonságos, mert nem lehet másik unique_ptr
példányra másolni.
✅ Hatékony, mivel nincs referencia számlálás.
#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> ptr = std::make_unique<int>(42); // Új érték foglalása
std::cout << "Érték: " << *ptr << std::endl;
// Nem lehet másolni! (Ez hiba lenne)
// std::unique_ptr<int> ptr2 = ptr;
// Átadhatjuk másik `unique_ptr`-nek `std::move()`-val
std::unique_ptr<int> ptr2 = std::move(ptr);
std::cout << "ptr2 értéke: " << *ptr2 << std::endl;
return 0;
} // A memória automatikusan felszabadul
Kimenet:
Érték: 42 ptr2 értéke: 42
🔹 Fontos!
- Egy unique_ptr
nem másolható, csak átadható (std::move
).
- Az objektum automatikusan felszabadul, amikor a mutató elhagyja a hatókört.
std::shared_ptr
– Megosztott tulajdonú mutatóAz std::shared_ptr
olyan okosmutató, amely több példányban is létezhet, és egy referenciaszámlálóval tartja nyilván, hogy hány shared_ptr
hivatkozik az adott objektumra.
✅ Több shared_ptr
példány is mutathat ugyanarra az objektumra.
✅ Az objektum csak akkor törlődik, ha az utolsó shared_ptr
is megszűnik.
✅ Biztonságosabb, mint a sima mutatók, mert elkerüli a vad mutatókat.
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> ptr1 = std::make_shared<int>(100); // Új érték foglalása
std::shared_ptr<int> ptr2 = ptr1; // Megosztott tulajdonjog
std::cout << "Érték: " << *ptr1 << std::endl;
std::cout << "Referencia számláló: " << ptr1.use_count() << std::endl;
return 0;
} // Az objektum automatikusan törlődik, ha nincs több hivatkozás rá
Kimenet:
Érték: 100 Referencia számláló: 2
🔹 Fontos!
- Több shared_ptr
példány is birtokolhatja ugyanazt az objektumot.
- Referencia számláló (use_count()
) nyomon követi, hány shared_ptr
hivatkozik az objektumra.
std::weak_ptr
– Gyenge mutató (Ciklikus referenciák elkerülése)A std::weak_ptr
egy “gyenge” mutató, amely egy shared_ptr
-re mutathat, de nem növeli a referencia számlálót.
Ez akkor hasznos, ha el akarjuk kerülni a ciklikus referenciákat.
Ha két shared_ptr
objektum egymásra mutat, akkor azok soha nem lesznek felszabadítva, mert a referencia számlálójuk soha nem csökken nullára.
#include <iostream>
#include <memory>
class A {
public:
std::shared_ptr<A> ptr; // Ha ez shared_ptr, ciklikus hivatkozás jön létre!
~A() { std::cout << "A objektum törölve" << std::endl; }
};
int main() {
std::shared_ptr<A> obj1 = std::make_shared<A>();
std::shared_ptr<A> obj2 = std::make_shared<A>();
obj1->ptr = obj2; // Ciklikus hivatkozás!
obj2->ptr = obj1; // Soha nem törlődnek!
return 0;
} // Memóriaszivárgás!
🔴 Probléma:
- obj1
és obj2
egymásra mutat, ezért egyik shared_ptr
sem törlődik.
✅ Megoldás: Használjunk weak_ptr
-t!
class A {
public:
std::weak_ptr<A> ptr; // Gyenge mutató, nem növeli a referencia számlálót
~A() { std::cout << "A objektum törölve" << std::endl; }
};
shared_ptr
eltűnik.
Okosmutató | Mikor használd? | Fő jellemzők |
---|---|---|
std::unique_ptr
|
Ha csak egy tulajdonos van | Nem másolható, automatikus felszabadítás |
std::shared_ptr
|
Ha több mutató kell egy objektumhoz | Referenciaszámlálás, több tulajdonos |
std::weak_ptr
|
Ha el akarod kerülni a ciklikus referenciákat | Nem növeli a referencia számlálót |
✅ Használj std::unique_ptr
-t, ha az objektumnak csak egy tulajdonosa van!
✅ Használj std::shared_ptr
-t, ha több objektum is megosztja a memóriát!
✅ Használj std::weak_ptr
-t, hogy elkerüld a ciklikus referenciákat!