2. RAII — The Foundation of C++ Engineering
RAII (Resource Acquisition Is Initialization) is the idea that:
If you own a resource, your object’s lifetime manages it.
This applies to:
- GPU buffers
- shader programs
- windows
- input contexts
- timers
- file handles
- memory blocks
Instead of:
particle* particles = new particle[1000]; // manual ownership: easy to leak if cleanup is missed
delete [] particles; // cleanup must be paired explicitly
A better approach is to wrap that ownership in a small template class that manages a fixed array of objects:
template <typename T>
class ppg_array {
T* m_data;
size_t m_size;
public:
ppg_array() : m_data(nullptr), m_size(0) {}
ppg_array(size_t size) : m_data(new T[size]), m_size(size) {}
~ppg_array() { delete[] m_data; } // releases owned storage automatically
void resize(size_t new_size) {
delete[] m_data;
m_data = new T[new_size];
m_size = new_size;
}
size_t size() const { return m_size; }
T& operator[](size_t index) { return m_data[index]; }
const T& operator[](size_t index) const { return m_data[index]; }
T* data() { return m_data; }
const T* data() const { return m_data; }
// provide begin() and end() methods for range-based for loops
T* begin() { return m_data; }
T* end() { return m_data + m_size; } // one-past-the-end pointer used by range-based iteration
const T* begin() const { return m_data; }
const T* end() const { return m_data + m_size; }
};
The usage becomes straightforward:
ppg_array <particle> particles(1000); // storage is owned by the array object
We no longer need to call delete[] manually. The array storage is released automatically when the particles
object is destroyed at the end of its scope.
The Playground uses a slightly different layout in practice, one that better supports GPU updates while the application runs: particle
positions, velocities, and colors are stored in separate arrays.
struct particle_system {
ppg_array<point3> positions;
ppg_array<vector3> velocities;
ppg_array<vector3> colors;
};
RAII helps provide:
- deterministic cleanup for owned resources
- fewer missed release paths
- less reliance on global shutdown functions
- fewer ownership questions during debugging
RAII therefore becomes more than a convenience; it becomes a core mechanism for reliable engine architecture. Once lifetimes
are controlled, the next question is what the rest of the code is allowed to see.