# C++ Resource Acquisition is Initialization (RAII) ## Resource Acquisition is Initialization (RAII) * reference: https://www.youtube.com/watch?v=T3etG2THif8&t=190 * a fundamental concept in **C++ programming** that leverages the **language's object lifecycle management features** specifically **constructors** and vdestructors** to manage resource allocation and deallocation automatically. * This design pattern ensures that resources such as **dynamic memory**, **file handles**, **network connections**, and more are **properly released when they are no longer needed**, which helps to **avoid resource leaks** and ensures more robust code. * In the RAII pattern, resources are **encapsulated within objects** * benefit * **Exception Safety**: By managing resources automatically, RAII handles resource deallocation even in the face of exceptions. This makes RAII a cornerstone of writing exception-safe code in C++. * **Resource Leak Prevention**: By tying resource management to the lifetime of objects, RAII **ensures** that resources are not inadvertently left allocated after they are no longer needed. * **Simplicity and Safety**: RAII can simplify code by **abstracting** the resource management tasks into the lifecycle of objects, **making the code cleaner and safer**. * example 1. **managing a mutex in a multi-threaded application**, use RAII to ensure that a mutex is locked when needed and automatically released ``` #include <mutex> #include <iostream> class Lock { std::mutex& mtx; public: Lock(std::mutex& m) : mtx(m) { mtx.lock(); std::cout << "Lock acquired" << std::endl; } ~Lock() { mtx.unlock(); std::cout << "Lock released" << std::endl; } }; int main() { std::mutex mtx; { Lock lock(mtx); // Do thread-safe work here } // Lock is automatically released when going out of scope return 0; } ``` 2. **RAII in Standard Library**, The C++ Standard Library makes extensive use of RAII. For instance, smart pointers such as std::unique_ptr and std::shared_ptr use RAII to manage dynamic memory. When a smart pointer goes out of scope, it automatically deallocates the memory it owns, thus preventing memory leaks ``` #include <memory> void function() { std::unique_ptr<int> ptr(new int(10)); // Automatically deleted when function returns // Use ptr } // ptr goes out of scope and the memory is deallocated automatically ``` 3. management dynamic memory: 假如今天想要dynamic allocate一個memory(在這裡是array),那programmer除了```new```,在程式結束前還要記得```delete```,否則會造成memory leak問題。however當project很大時,此創自出來object歸屬誰又甚麼時候要delete很難分界而且容易忘掉造成memory leak。因此如何妥善處理memory回收問題很重 * **bad implement**: 使用者直接使用new,但有可能會忘記造成memory leak ``` int main(){ arr = new int[10]; // operation arr[0] = 7; // forget to delete the dynamically allocated memory(arr) here!!! memory leak return 0; } ``` * **good implement**: 我們可以利用c++中class object在其life cycle開始及結束前會執行constructor以及destructor的特性來把要new的東西包在object中,並且使用將```new```放在constructor,而```delete```放在destructor,如此不管怎樣,此物件一定會在程式結束前被delete掉 * 這裡有一個時做細節,當我們要用class來把這些資料結構(arr,int,...)包起來時,我們也要在class method中定義原本資料結構所擁有的operator,如此才可以讓此class用起來像是原本的資料結構 * [原本資料結構中所用到operator長怎樣?](<https://en.cppreference.com/w/cpp/language/operators>) * c++ operator overload文件定義了不同operator長怎樣, * 進入網站中用```ctrl+f```找到對應operator符號對應資料結構的定義方式 * 然後將class(資料結構封裝)所要用到operator複製到class method中 ``` // good implement class collection{ public: collection(){ arr = new int[10]; } ~collection(){ delete[] arr; } int& operator[](std::size_t idx){ return data[idx]; } const int& operator[](std::size_t idx) const{ return data[idx]; } private: int* arr; } int main(){ collection coll1; // operation on collection object like the normal arr coll1[0] = 7; coll1[1] = 2; std::cout << coll1[0] << std::endl; return 0; } ``` ## exception safe code reference: