What I understand from RAII is whenever you need to allocate memory manually with new
etc. you need to free it too. So, instead of freeing it manually, you should create classes with constructor and destructor to do the job.
So, what are the following people talking about?
From: The meaning of the term - Resource Acquisition Is Initialization
The problem is that int * p = malloc(1000); is also initialization of an (integer) object, but it's not the kind of initialization we mean in the context of RAII. ...
@Fred: Indeed. int* is not a RAII type because it doesn't do cleanup. So it's not what RAII means, even though it is what RAII literally says.
Well, I know malloc
is used in C, and new
is used in C++.
Using malloc per se is not RAII because the resources are not freed when the variable goes out of scope, causing leaks of memory. You can make it RAII if you wrap this inside a class and free the resources in the destructor, because local class instances do die when they go out of scope. However, it should be noted what is being discussed here: the int *
type is not RAII, and if you enclose it in a RAII type it still isn't. The wrapper doesn't make it RAII, so the RAII type here is the wrapper, not the pointer itself.
As requested in the comments: RAII stands for Resource Acquisition Is Initialisation and it's a design paradigm that combines the allocation of resources with the initialisation and destruction of objects. You don't seem far from understanding it: when an object is instantiated it allocates all the necessary resources (memory, file descriptors, streams, and so on) and frees them when it goes out of scope or the object is otherwise destructed. This is a common paradigm in C++ because C++ classes are RAII (that is, they die when they go out of scope) and as such it's easy to guarantee proper cleanup. The obvious upside being that you don't need to worry about manual cleanup and tracking variable lifetime.
On a related note, notice that this refers to stack allocation, not heap. What this means is that whatever the means you use for allocation (new/malloc vs delete/free) it still isn't RAII; memory that is allocated dynamically does not get magically freed, that's a given. When a variable is allocated on the stack (local variables) they are destroyed when the scope dies.
Example:
class MyObject
{
public:
MyObject()
{
// At this point resources are allocated (memory, files, and so on)
// In this case a simple allocation.
// malloc would have been just as fine
this->_ptr = new int;
}
~MyObject()
{
// When the object is destructed all resources are freed
delete this->_ptr;
}
private:
int * _ptr;
};
The previous sample code implements a RAII wrapper over a native pointer. Here's how to use it:
void f()
{
MyObject obj;
// Do stuff with obj, not including cleanup
}
In the previous example the int pointer is allocated when the variable is instantiated (at declaration time) and freed when the f
call terminates, causing the variable to go out of scope and calling its destructor.
Note: As mentioned in the comments by Jarod42 the given example does not conform to the rule of 3 or the rule of 5, which are common thumb rules in C++. I would rather not add complexity to the given example, and as such I'll complete it here. These rules indicate that, if a method from a given set is implemented, then all methods of the set should be implemented, and those methods are the copy and move constructors, the assignment and move operators, and the destructor. Notice at first that this is a general rule, which means that is not mandatory. For instance, immutable objects should not implement assignment and move operators at all. In this case, if the object is to implement these operators it would probably imply reference counting, as multiple copies of the resource exist the destructor must not free the resources until all copies are destroyed. I believe that such an implementation would fall out of scope and as such I'm leaving it out.