Logo Xingxin on Bug

3 Lines of Code Convince You to Use RAII in C++

January 4, 2025
3 min read
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

  1. complicate logics
  2. another function
  3. untrustful 3rd party library function call
  4. 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.