resource acquisition is initialization (tsz. resource acquisition is initializations)
A RAII egy tervezési minta, amelynek lényege:
👉 egy erőforrás élettartama kötődjön egy objektum élettartamához.
Az “erőforrás” lehet például:
A lényeg:
“Resource Acquisition Is Initialization” szó szerint:
“Az erőforrás megszerzése az inicializálás során történik.”
Vagyis:
Manuális erőforrás-kezelés során könnyű hibázni:
void myFunction() {
FILE* f = fopen("data.txt", "r");
if (!f) return; // Oops, early return → resource leak
// Use the file
processFile(f);
if (someError) return; // Oops again → resource leak
fclose(f); // ok, ha ide eljutunk
}
Hiba:
fclose(f)
már nem fut le → fájl leak lesz.
RAII mintával a fenti kód így nézne ki:
#include <fstream>
void myFunction() {
std::ifstream f("data.txt");
if (!f) return; // Ok! Ha elhagyjuk a scope-ot, a destructor bezárja a fájlt.
// Use the file
processFile(f);
if (someError) return; // Ok! Destructor automatikusan lezárja.
}
Itt a std::ifstream
osztály RAII-t alkalmaz:
Tehát a return
hívások teljesen biztonságosak lettek.
✅ Nincs resource leak — automatikusan tisztítunk.
✅ Exception safety — ha kivétel dobódik, a destructor mindenképp lefut, és felszabadítja az erőforrást.
✅ Egyszerű, tiszta kód — nincs szükség külön release() hívásokra.
✅ Scope-hoz kötött élettartam — ha kilépünk egy scope-ból, az erőforrás automatikusan tisztul.
#include <memory>
void foo() {
std::unique_ptr<MyObject> ptr(new MyObject());
ptr->doSomething();
} // amikor kilépünk a foo()-ból, a MyObject automatikusan törlődik.
A std::unique_ptr
alkalmazza a RAII mintát:
#include <mutex>
std::mutex mtx;
void criticalSection() {
std::lock_guard<std::mutex> lock(mtx);
// A lock_guard megszerzi a lockot, scope végén automatikusan elengedi.
doCriticalWork();
}
A std::lock_guard
is RAII:
Exception-safe! Ha kivétel dobódik, a lock felszabadul.
#include <fstream>
void readData() {
std::ifstream file("data.txt");
std::string line;
while (std::getline(file, line)) {
// process line
} // file automatikusan lezáródik scope végén
}
Pl.:
class MyFile {
FILE* file;
public:
MyFile(const char* filename) {
file = fopen(filename, "r");
if (!file) throw std::runtime_error("Cannot open file");
}
~MyFile() {
if (file) fclose(file);
}
// Egyéb függvények...
};
Használat:
void myFunction() {
MyFile f("data.txt");
// Use f...
} // f destruktora automatikusan hívódik → fclose megtörténik.
Az RAII különösen kivételbiztos:
Ezért RAII kötelező minden olyan erőforrás kezelésénél, ahol leak veszély áll fenn.
Elv | Resource Acquisition Is Initialization (RAII) |
---|---|
Cél | Az erőforrás életciklusa kötődjön az objektum életciklusához |
Hogyan | Konstruktor: acquire, Destruktor: release |
Előny | Memory-safe, exception-safe, tiszta kód |
Példák | std::unique_ptr, std::lock_guard, std::ifstream, saját RAII osztályok |
Hova használható | Memória, fájl, mutex, hálózat, adatbázis, grafikai erőforrás |
A C++ egyik legfontosabb elve:
“Ami megszületik, az automatikusan pusztuljon is el a megfelelő időben.”
Vagy:
👉 “Kövesd az objektumok életciklusát, ne kezeld kézzel az erőforrásokat.”
Ezért a modern C++-ban:
❌ new / delete — ne használd közvetlenül, inkább std::unique_ptr
❌ malloc / free — ne használd
❌ fopen / fclose — inkább std::ifstream
❌ pthread_mutex_lock / unlock — inkább std::lock_guard
A RAII a C++ egyik legerősebb és legbiztonságosabb mintája. Használata:
Ma már alapszabálynak számít:
👉 “Ha valamilyen erőforrást használsz, rakd RAII-be!”