Resource Acquisition is Initialisation a.k.a RAII

NamyaLG
3 min readJul 5, 2023

It is always expected that you give back what is not yours/what you have borrowed to the rightful owners. This ensures that those in need get what they want, and it does not lead to wasteful blockage of resources, i.e. you do not need the resources anymore, but you haven’t returned it back. Sounds philosophical? Well, in brief, this is my understanding of RAII in C++

Memory is a very precious resource and is to be used with utmost caution. At the very core, writing and running programs revolves around the conversion of source code to machine code, storing it in memory, retrieving the program, and interacting with the program data, summarizing; with great power comes great responsibility : ))

In C++, it is possible to allocate memory for objects and primitives on the stack or heap. Allocating memory on the heap is referred to as Dynamic memory allocation. This is done using new and delete operators.

Given the datatype and size, the new operator returns the address of the memory allocated on the heap or else reports an Out Of Memory exception.

Allocation and Deallocation of an integer on the heap

Once the memory is allocated on the heap, after use, it is the responsibility of the developer to free the memory. C++ does NOT do the cleanup process automatically. This is good and bad as it offers freedom and flexibility to handle memory allocation and deallocation, however, this increases the probability of the occurrence of memory leaks; memory that is allocated on the heap but not deallocated. In most cases, the variable pointing to the memory goes out of scope, and hence the only way to access the heap memory is lost. The overhead due to memory leaks can be very high.

Memory is one of the resources that needs to be allocated and deallocated. There can be other resources such as file handles, which need to be opened and closed, mutexes and locks that need to be held and released, so as to offer synchronization between different threads.

In all the above-mentioned resources, a common requirement is — An automatic way to perform the allocation and deallocation of the resource.

Stack variables are bound to the scope they are defined in. For each function or scope (defined using {}), an execution stack frame is pushed. The stack frame consists of the local variables and the data that is specific to that scope. On completion of the execution of that scope, the stack is popped, i.e the data associated with that stack frame is no longer accessible. This implies that the lifetime is bounded by the scope.

This is an important takeaway. In general, an Object construction involves the invocation of the constructor when the Object is in scope, and the invocation of the constructor when the Object goes out of scope. This idea is used as leverage to automate the process of allocation and deallocation of resources; i.e the Constructor allocates/initializes the resource, while the Destructor deallocates the resource.

Smart Pointers employ the same idea, i.e a class wrapped around a raw pointer, where the constructor does the memory allocation, while the destructor does the memory deallocation. Irrespective of the exceptions raised or the flow the program follows, the constructor and destructor will always be invoked.

The following code snippet is the implementation of a wrapper class around a raw pointer.

#include<iostream>


class SmartInteger {
int* integer;

public:
SmartInteger(int value) {
// Allocate memory in the constructor
integer = new int;
*integer = value;
std::cout << "Constructor is invoked, allocating memory and assigning the value " << std::endl;
}


~SmartInteger() {
// Deallocate memory in the destructor
std::cout << "Destructor is invoked, deallocating memory " << std::endl;
delete integer;
}

int get_integer() const {
return *integer;
}
};


int main() {

SmartInteger smart_integer(18);

std::cout << " The value of the integer is " << smart_integer.get_integer() << std::endl;

return 0;
}
Demonstration of the invocation of the constructor and destructor in the object scope

To conclude, the automated management of the allocation and deallocation of resources offers a safer and secure execution environment.

--

--

NamyaLG

Tech-enthusiast | Runner_for_life | #NoHumanIsLimited