void suspicious()
{
int* p = new int[13]; // Line 1: Allocate memory
// . . .👈 Line 2: 🏃➡️What if an exception is thrown here?
delete[] p; // Line 3: ❌Release memory(never reach here)
}
That’s it. That is my 3 lines of code convincing you to use RAII in C++. I know there are many benefits using RAII. But I really like these 3 line as it is simple enough to warn you to adopt RAII daily.
Remark
By the way, Bjarne Stroustrup states that RAII is the most important subject of C++ in his book Programming: Principles and Practice Using C++.
⛳The Problem
In these 3 lines, the function suspicious()
allocates memory dynamically. But if an exception is thrown in “Line 2”, the delete[]
statement in Line 3 is never executed, resulting in a memory leak(no one will release the memory).
Remark
In real world application, the “Line 2” might be
- complicate logics
- another function
- untrustful 3rd party library function call
- on and on and on…
🏌️The Solution
Now, let’s fix this with RAII. By using std::vector
, we can ensure that resources are automatically managed, even if an exception occurs:
#include <memory>
#include <vector>
void safe_function()
{
std::vector<int> v(13); //👈the numbers are in the heap as well
// 💀exception. . .
}
//👈 No leaks, no worries!
Even if there is an exception thrown, the memory managed by the std::vector
will automatically be released. No manual delete
is needed, and your code is exception-safe.
💡Core Idea of RAII
The “automatic release” is implemented by a very simple but elegant approach. There are just 2 entities to finish this story:
- constructor: who acquire the resource
- destructor: who release the resource
Here’s a simplified version of std::vector<T>
:
template <typename T>
class vector {
private:
T* data;
public:
// Constructor: acquires resources when initialized
vector() {
data = new int[13];
}
// Destructor: Releases resources
~vector() {
delete[] data;
}
Therefore, this is RAII (resource acquisition is initialization).
- constructor is the first guy deal with the resource(acquire)
- destructor is the last guy deal with the resource(release)
When the variable is out of scope, the destructor will automatically called therefore destructs the resource.