Understanding C++ syntax for an experienced C programmer - c++

I am looking through the source code for MongoDB, and see the following declaration inside of a function, which I don't understand and haven't seen in my C programming experience.
Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_X);
I am trying to understand what this declaration is doing in C++ terms (ie. I want to understand the syntax, not specifics about the functionality of what is going on).
This breaks down into two main questions:
1) What is the purpose of the Lock::DBLock statement in front of the function?
2) Is this a function call, or a function declaration?

It is a variable declaration with a constructor - so it's BOTH a function call [to the object constructor] and a declaration of a variable.
It declares a variable of the type;
Lock::DBLock
The variable is called dbLock. It calls the constructor with a txn->lockState(), the ns.db() and a MODE_X.
My guess is that txn->lockState actually returns a lock-object, and the thing we're locking is ns.db() - in "exclusive mode". But that's a guess, and you have to look those things up within the environment.
Without looking up the documentation, I expect Lock::DBLock is a "lock manager", in other words, it takes the lock when created, and releases when destroyed.
A simple lock manager would look something like this:
class LockMgr
{
LockMgr(SomeLockType &X) : keeper(X)
{
keeper.Lock();
}
~LockMgr()
{
keeper.Unlock();
}
private:
SomeLockType& keeper; // Must be reference to original lock
};
The destructor is automatically called when the variable goes out of scope (in other worse when you leave the {} pair that the variable is within.
In C++, one commmon strategy for "resource handling" is called RAII (Resource Acquisition Is Initialization) - a variable is used to hold a resource, and it is assigned during initialization. This helps a lot with "not forgetting to undo" - for example in code that returns in the middle of the function, does break to exit a loop, or similar things. In C, you always have to watch your step for releasing locks, closing files, freeing memory, etc - and of course, if you use C++ in the wrong way, you can fall into the same pitfalls there - calling new will definitely need a call to delete, directly calling a locks Lock() member function requires a Unlock() call somewhere. But if we "wrap" the resource into an object that holds it for the duration we need it, and automatically "lets go" (frees, unlocks, etc) in the destructor, there's no need to remember to release memory, unlock locks, etc, etc.
I would suggest that before asking further questions, you read the first chapter about classes and constructor & destructor pairs in your C++ book (you DO have a book, right?)

The code is the declaration of a variable named dbLock of type Lock::DBLock. The parenthesized list contains arguments to a constructor for that type.

Related

Is there a way to 'detect' or get around singleton destruction (without leaking)?

I have a handrolled and simplistic logsystem - however the way it works it does have to track some global state. The way it is done is through a meyer's singleton that gets initialized on first use. However, this seems to have the drawback: it is possible to call for something to get logged after the singleton has been destroyed (unless the order is known - which can be difficult to assert in larger program) - leading to UB (crash on shutdown most likely).
low-level Log function looks something like this:
void logImpl(const char* log, const std::string& message, Severity::Type level) {
static LogSys& logSys = LogSys::instance();
...
}
I could of course force the problem onto the 'user' of the library, but that doesn't really solve the issue (still manual handling). Will making it an inline static in .h solve anything ?(I guess not). We have the destructor of the singleton run, but is it meaningfull to write to anything to indicate it was destroyed ? another meyer's singleton ? What happends if you initialize a meyer's singleton during static destruction ?
Single responsibility principle: Create a function whose sole purpose is to create the singleton on first use, and return it.
The only case where a static object could be destroyed before logging is if the log message is sent from from the destructor of a(nother) static object. If a destructor (or any other member function) may want to log, then call the singleton getter in the constructor. This enforces the correct order of destruction.
There is still bit of a problem in case the destructor calls a function and logging happens indirectly and unexpectedly. The above convention solves the problem when calling any member function, but the problem remains if there is call to any free function which cannot enforce the order. This problem could be avoided if you constrain yourself from ever using the singleton from any free function. If you cannot bring yourself to such constraint (understandable), then you could simply add call to the constructor of every static object to enforce the order just in case.
None of these constraints can be enforced within the language however, which is unfortunate. This is why dependencies between static objects are to be avoided like the plague - an static objects in general to some lesser degree.

Vector of Pointers, syntax for pushing element

vector<thread>* myVector;
Is what I used to declare a vector of thread pointers.
thread* new_thread = new thread(chef_thread,&kill, new std::mutex, &foodQ,
numberChefs); //New Thread
myVector->push_back(*new_thread);
Chef_Thread is a function that I made that's declared above in the same .cpp file.
I try compiling the code and everything goes to hell.
Thanks!
vector<thread>* myVector; declares a pointer to a vector of threads.
The type you're looking for is vector<thread*>, which declares a vector of thread pointers.
user2899162 is correct in pointing out the immediate error in your code. However I doubt there is any need to use pointers at all.
As a general rule: You should not have raw – i.e. manually typed – new and delete in your program. Because that is manual resource management and you will get it wrong. Use RAII instead, i.e. rely on constructors and automatic execution of destructors at the end of an object’s scope to avoid manual resource management. [1]
std::vector<std::thread> threads;
threads.push_back(std::thread(
chef_thread,
&kill,
std::mutex(), // this is weird, see below
&foodQ,
numberChefs));
All thread and mutex objects as well as the vector itself will be destroyed automatically as soon as threads goes out of scope.
Now for the weirdness: the standalone mutex (the new std::mutex argument in your code). That creates a mutex object that is only known to the chef_thread function. We’d need more code to say anything definitive, but I smell an error here. A mutex is a sync machanism for a shared resource. Everyone accessing the resource must do so via the same mutex. But how can that be possible if only the one function knows about the mutex? The only way I see is passing along a reference or pointer to the mutex from inside chef_thread, which is a red flag itself.
[1] There are, of course, exceptions to this rule. The obvious one is a wrapper/container class that has new in its constructor and the corresponding delete in its destructor. In a nutshell that’s how you implement RAII and that’s how all std containers, smart pointers and other resource wrappers work.

Possible to detect stack allocated object that isn't captured?

Is it possible to prevent or detect the following bug, in any way (static analysis), where the stack allocated object is not captured and goes out of scope on the same line that it was constructed?
Resource resourceA, resourceB;
void someFunction()
{
ScopedResourceBinder resourceBindA( resourceA );
ScopedResourceBinder( resourceB ); // <--- BUG
}
The first ScopedResourceBinder is correct, but the second one doesn't do anything, since it immediately 'unbinds' right after it 'binds' (hypothetically speaking).
This is clearly a programmers error, but I have debugged this a few times now (for hours on a couple occassion) and it is extremely difficult to spot. Once you see it you think "ah that was a stupid one", but in practice, it is easy to make the mistake and the compiler is defenseless... or is it?
Background info: I work with a library that makes heavy use RAII class for pushing an popping state, for example OpenGL resources. Managing the bindings with scope is a big improvement of manually calling bind() / unbind() functions, but the potential bug listed here comes up with this new pattern.
ScopedResourceBinder( resourceB ); is the same as ScopedResourceBinder resourceB;, i.e. it declares a named variable with name resourceB, calling the default constructor of ScopedResourceBinder.
This persists until the end of the function, however it is still a bug because it does not carry out your intent of binding to the variable resourceB.
To prevent this particular case you could make sure that ScopedResourceBinder does not have a default constructor.
In general coding practice, we should explicitly express our intent in the class definition itself.
For eg:
If we want to have singleton class, then all the constructors should be made private.
If we want to constructs an object with some variables, then only the required constructor should be exposed publicly, rest all should be mentioned as private.
In this manner we would be able to flag all wrong usage during compile time only.

Leaving a c++ application without running destructors of global static objects

I have "inherited" a design where we are using a few global objects for doing stuff when the application exits (updating application status log files, etc ... not important to the question).
Basically the application creates dummy helper objects of specific classes and lets their destructor do these extra works when the application exits either normally or when an error was encountered (and the application knows what to do in all the cases, again not relevant to the question).
But now I have encountered a situation where I do not want to call these destructors, just leave the application without executing these "termination jobs". How can I do this in a decent, platform independent way? I do not want a solution such as divide with zero :)
Edit: I know the design is broken :) We are working on fixing it.
Edit2: I would like to avoid any "trace" of abnormal exit... Sorry for late specification.
Edit3: Obtaining access to the source code for the destructors in order to modify them is very difficult. This happens when politicians take over the keyboard and try to write programs. We just know, that "their" destructor will run on exit...
How can I do this in a decent, platform independent way?
You can't. At least not in a decent way.
You can accomplish this by throwing an exception and not catching it. The end result will be that your application will terminate quite ungracefully. Destructors will not be called. This is quite ugly, very hackish. If your design relies on this behavior to function correctly, well not only is your design completely demented, but it will be near-impossible to maintain.
I would prefer setting a boolean flag in the objects you don't want to run the destructors for. If this flag is set, then the destruction code would not be run. The destructors will still fire, but the actual code you want to avoid running can be skipped.
If you control the construction of the global, you might be able to leverage operator placement-new. Construct a global char buffer big enough for your global, then placement-new your global there. Since objects constructed this way must be destroyed by explicitly calling the destructor, simply don't call the destructor on shutdown for the global.
abort();
Aborts the current process, producing an abnormal program termination.
The function raises the SIGABRT signal (as if raise(SIGABRT) was
called). This, if uncaught, causes the program to terminate returning
a platform-dependent unsuccessful termination error code to the host
environment.
The program is terminated without destroying any object and without
calling any of the functions passed to atexit or at_quick_exit.
Taking your comment of "we know it's broken"...
Put a global bool somewhere
bool isExiting;
Set this to true when exiting.
In your destructors do
if( !global::isExiting )
{
// destruction code here
}
Hide somewhere, and be thoroughly ashamed.
The easiest is to replace the global objects by heap-allocated pointers to the objects. That way, in order to run their destructors, you have to manually delete them. Be aware that this is of course very, very nasty. A better way than using a raw pointer is to use a std::unique_ptr and, in case the destructor shouldn’t be called, release it.
If you don’t want to change the client code which is interacting with the global objects (and expect a non-pointer type), just wrap the actual pointer into a global proxy object.
(PS: There are few but very legitimate reasons for such a design. Sometimes it’s entirely safe not to call destructors, and calling them may be detrimental, e.g. because it’s known that they only release memory, but will take very long due to many nested destructor calls. This still needs to be done very carefully but is not at all “bad design”.)
It is ugly but it works:
Create simple maker class.
Maker's constructorr should allocate the object of your liking and assign it to a static pointer.
Make sure that nothing is done in maker's destructor.
Create single static instance of maker object.
To make things look better, make the static pointer private andwrite inline accessor function that will convert the static pointer you have to a public reference.

Understanding the meaning of the term and the concept - RAII (Resource Acquisition is Initialization)

Could you C++ developers please give us a good description of what RAII is, why it is important, and whether or not it might have any relevance to other languages?
I do know a little bit. I believe it stands for "Resource Acquisition is Initialization". However, that name doesn't jive with my (possibly incorrect) understanding of what RAII is: I get the impression that RAII is a way of initializing objects on the stack such that, when those variables go out of scope, the destructors will automatically be called causing the resources to be cleaned up.
So why isn't that called "using the stack to trigger cleanup" (UTSTTC:)? How do you get from there to "RAII"?
And how can you make something on the stack that will cause the cleanup of something that lives on the heap? Also, are there cases where you can't use RAII? Do you ever find yourself wishing for garbage collection? At least a garbage collector you could use for some objects while letting others be managed?
Thanks.
So why isn't that called "using the stack to trigger cleanup" (UTSTTC:)?
RAII is telling you what to do: Acquire your resource in a constructor! I would add: one resource, one constructor. UTSTTC is just one application of that, RAII is much more.
Resource Management sucks. Here, resource is anything that needs cleanup after use. Studies of projects across many platforms show the majority of bugs are related to resource management - and it's particularly bad on Windows (due to the many types of objects and allocators).
In C++, resource management is particularly complicated due to the combination of exceptions and (C++ style) templates. For a peek under the hood, see GOTW8).
C++ guarantees that the destructor is called if and only if the constructor succeeded. Relying on that, RAII can solve many nasty problems the average programmer might not even be aware of. Here are a few examples beyond the "my local variables will be destroyed whenever I return".
Let us start with an overly simplistic FileHandle class employing RAII:
class FileHandle
{
FILE* file;
public:
explicit FileHandle(const char* name)
{
file = fopen(name);
if (!file)
{
throw "MAYDAY! MAYDAY";
}
}
~FileHandle()
{
// The only reason we are checking the file pointer for validity
// is because it might have been moved (see below).
// It is NOT needed to check against a failed constructor,
// because the destructor is NEVER executed when the constructor fails!
if (file)
{
fclose(file);
}
}
// The following technicalities can be skipped on the first read.
// They are not crucial to understanding the basic idea of RAII.
// However, if you plan to implement your own RAII classes,
// it is absolutely essential that you read on :)
// It does not make sense to copy a file handle,
// hence we disallow the otherwise implicitly generated copy operations.
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// The following operations enable transfer of ownership
// and require compiler support for rvalue references, a C++0x feature.
// Essentially, a resource is "moved" from one object to another.
FileHandle(FileHandle&& that)
{
file = that.file;
that.file = 0;
}
FileHandle& operator=(FileHandle&& that)
{
file = that.file;
that.file = 0;
return *this;
}
}
If construction fails (with an exception), no other member function - not even the destructor - gets called.
RAII avoids using objects in an invalid state. it already makes life easier before we even use the object.
Now, let us have a look at temporary objects:
void CopyFileData(FileHandle source, FileHandle dest);
void Foo()
{
CopyFileData(FileHandle("C:\\source"), FileHandle("C:\\dest"));
}
There are three error cases to handled: no file can be opened, only one file can be opened, both files can be opened but copying the files failed. In a non-RAII implementation, Foo would have to handle all three cases explicitly.
RAII releases resources that were acquired, even when multiple resources are acquired within one statement.
Now, let us aggregate some objects:
class Logger
{
FileHandle original, duplex; // this logger can write to two files at once!
public:
Logger(const char* filename1, const char* filename2)
: original(filename1), duplex(filename2)
{
if (!filewrite_duplex(original, duplex, "New Session"))
throw "Ugh damn!";
}
}
The constructor of Logger will fail if original's constructor fails (because filename1 could not be opened), duplex's constructor fails (because filename2 could not be opened), or writing to the files inside Logger's constructor body fails. In any of these cases, Logger's destructor will not be called - so we cannot rely on Logger's destructor to release the files. But if original was constructed, its destructor will be called during cleanup of the Logger constructor.
RAII simplifies cleanup after partial construction.
Negative points:
Negative points? All problems can be solved with RAII and smart pointers ;-)
RAII is sometimes unwieldy when you need delayed acquisition, pushing aggregated objects onto the heap.
Imagine the Logger needs a SetTargetFile(const char* target). In that case, the handle, that still needs to be a member of Logger, needs to reside on the heap (e.g. in a smart pointer, to trigger the handle's destruction appropriately.)
I have never wished for garbage collection really. When I do C# I sometimes feel a moment of bliss that I just do not need to care, but much more I miss all the cool toys that can be created through deterministic destruction. (using IDisposable just does not cut it.)
I have had one particularly complex structure that might have benefited from GC, where "simple" smart pointers would cause circular references over multiple classes. We muddled through by carefully balancing strong and weak pointers, but anytime we want to change something, we have to study a big relationship chart. GC might have been better, but some of the components held resources that should be release ASAP.
A note on the FileHandle sample: It was not intended to be complete, just a sample - but turned out incorrect. Thanks Johannes Schaub for pointing out and FredOverflow for turning it into a correct C++0x solution. Over time, I've settled with the approach documented here.
There are excellent answers out there, so I just add some things forgotten.
##0. RAII is about scopes
RAII is about both:
acquiring a resource (no matter what resource) in the constructor, and un-acquiring it in the destructor.
having the constructor executed when the variable is declared, and the destructor automatically executed when the variable goes out of scope.
Others already answered about that, so I won't elaborate.
##1. When coding in Java or C#, you already use RAII...
MONSIEUR JOURDAIN: What! When I say, "Nicole, bring me my slippers,
and give me my nightcap," that's prose?
PHILOSOPHY MASTER: Yes, Sir.
MONSIEUR JOURDAIN: For more than forty years I have been speaking prose without knowing anything about it, and I am much obliged to you for having taught me that.
— Molière: The Middle Class Gentleman, Act 2, Scene 4
As Monsieur Jourdain did with prose, C# and even Java people already use RAII, but in hidden ways. For example, the following Java code (which is written the same way in C# by replacing synchronized with lock):
void foo()
{
// etc.
synchronized(someObject)
{
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
... is already using RAII: The mutex acquisition is done in the keyword (synchronized or lock), and the un-acquisition will be done when exiting the scope.
It's so natural in its notation it requires almost no explanation even for people who never heard about RAII.
The advantage C++ has over Java and C# here is that anything can be made using RAII. For example, there are no direct build-in equivalent of synchronized nor lock in C++, but we can still have them.
In C++, it would be written:
void foo()
{
// etc.
{
Lock lock(someObject) ; // lock is an object of type Lock whose
// constructor acquires a mutex on
// someObject and whose destructor will
// un-acquire it
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
which can be easily written as it would be in Java/C# (using C++ macros):
#define LOCK(mm_mutex) \
if(Lock lock{mm_mutex}) {} \
else
void foo()
{
// etc.
LOCK(someObject)
{
// if something throws here, the lock on someObject will
// be unlocked
}
// etc.
}
##2. RAII have alternate uses
WHITE RABBIT: [singing] I'm late / I'm late / For a very important date. / No time to say "Hello." / Goodbye. / I'm late, I'm late, I'm late.
— Alice in Wonderland (Disney version, 1951)
You know when the constructor will be called (at the object declaration), and you know when its corresponding destructor will be called (at the exit of the scope), so you can write almost magical code with but a line. Welcome to the C++ wonderland (at least, from a C++ developer's viewpoint).
For example, you can write a counter object (I let that as an exercise) and use it just by declaring its variable, like the lock object above was used:
void foo()
{
double timeElapsed = 0 ;
{
Counter counter(timeElapsed) ;
// do something lengthy
}
// now, the timeElapsed variable contain the time elapsed
// from the Counter's declaration till the scope exit
}
which of course, can be written, again, the Java/C# way using a macro:
void foo()
{
double timeElapsed = 0 ;
COUNTER(timeElapsed)
{
// do something lengthy
}
// now, the timeElapsed variable contain the time elapsed
// from the Counter's declaration till the scope exit
}
##3. Why does C++ lack finally?
[SHOUTING] It's the final countdown!
— Europe: The Final Countdown (sorry, I was out of quotes, here... :-)
The finally clause is used in C#/Java to handle resource disposal in case of scope exit (either through a return or a thrown exception).
Astute specification readers will have noticed C++ has no finally clause. And this is not an error, because C++ does not need it, as RAII already handle resource disposal. (And believe me, writing a C++ destructor is magnitudes easier than writing the right Java finally clause, or even a C#'s correct Dispose method).
Still, sometimes, a finally clause would be cool. Can we do it in C++? Yes, we can! And again with an alternate use of RAII.
##Conclusion: RAII is a more than philosophy in C++: It's C++
RAII? THIS IS C++!!!
— C++ developer's outraged comment, shamelessly copied by an obscure Sparta king and his 300 friends
When you reach some level of experience in C++, you start thinking in terms of RAII, in terms of construtors and destructors automated execution.
You start thinking in terms of scopes, and the { and } characters become ones of the most important in your code.
And almost everything fits right in terms of RAII: exception safety, mutexes, database connections, database requests, server connection, clocks, OS handles, etc., and last, but not least, memory.
The database part is not negligible, as, if you accept to pay the price, you can even write in a "transactional programming" style, executing lines and lines of code until deciding, in the end, if you want to commit all the changes, or, if not possible, having all the changes reverted back (as long as each line satisfy at least the Strong Exception Guarantee). (see the second part of this Herb's Sutter article for the transactional programming).
And like a puzzle, everything fits.
RAII is so much part of C++, C++ could not be C++ without it.
This explains why experienced C++ developers are so enamored with RAII, and why RAII is the first thing they search when trying another language.
And it explains why the Garbage Collector, while a magnificient piece of technology in itself, is not so impressive from a C++ developer's viewpoint:
RAII already handles most of the cases handled by a GC
A GC deals better than RAII with circular references on pure managed objects (mitigated by smart uses of weak pointers)
Still A GC is limited to memory, while RAII can handle any kind of resource.
As described above, RAII can do much, much more...
RAII is using C++ destructors semantics to manage resources. For example, consider a smart pointer. You have a parameterized constructor of the pointer that initializes this pointer with the adress of object. You allocate a pointer on stack:
SmartPointer pointer( new ObjectClass() );
When the smart pointer goes out of scope the destructor of the pointer class deletes the connected object. The pointer is stack-allocated and the object - heap-allocated.
There are certain cases when RAII doesn't help. For example, if you use reference-counting smart pointers (like boost::shared_ptr) and create a graph-like structure with a cycle you risk facing a memory leak because the objects in a cycle will prevent each other from being released. Garbage collection would help against this.
I'd like to put it a bit more strongly then previous responses.
RAII, Resource Acquisition Is Initialization means that all acquired resources should be acquired in the context of the initialization of an object. This forbids "naked" resource acquisition. The rationale is that cleanup in C++ works on object basis, not function-call basis. Hence, all cleanup should be done by objects, not function calls. In this sense C++ is more-object oriented then e.g. Java. Java cleanup is based on function calls in finally clauses.
I concur with cpitis. But would like to add that the resources can be anything not just memory. The resource could be a file, a critical section, a thread or a database connection.
It is called Resource Acquisition Is Initialization because the resource is acquired when the object controlling the resource is constructed, If the constructor failed (ie due to an exception) the resource is not acquired. Then once the object goes out of scope the resource is released. c++ guarantees that all objects on the stack that have been successfully constructed will be destructed (this includes constructors of base classes and members even if the super class constructor fails).
The rational behind RAII is to make resource acquisition exception safe. That all resources acquired are properly released no matter where an exception occurs. However this does rely on the quality of the class that acquires the resource (this must be exception safe and this is hard).
The problem with garbage collection is that you lose the deterministic destruction that's crucial to RAII. Once a variable goes out of scope, it's up to the garbage collector when the object will be reclaimed. The resource that's held by the object will continue to be held until the destructor gets called.
RAII comes from Resource Allocation Is Initialization. Basically, it means that when a constructor finishes the execution, the constructed object is fully initialized and ready to use. It also implies that the destructor will release any resources (e.g. memory, OS resources) owned by the object.
Compared with garbage collected languages/technologies (e.g. Java, .NET), C++ allows full control of the life of an object. For a stack allocated object, you'll know when the destructor of the object will be called (when the execution goes out of the scope), thing that is not really controlled in case of garbage collection. Even using smart pointers in C++ (e.g. boost::shared_ptr), you'll know that when there is no reference to the pointed object, the destructor of that object will be called.
And how can you make something on the stack that will cause the cleanup of something that lives on the heap?
class int_buffer
{
size_t m_size;
int * m_buf;
public:
int_buffer( size_t size )
: m_size( size ), m_buf( 0 )
{
if( m_size > 0 )
m_buf = new int[m_size]; // will throw on failure by default
}
~int_buffer()
{
delete[] m_buf;
}
/* ...rest of class implementation...*/
};
void foo()
{
int_buffer ib(20); // creates a buffer of 20 bytes
std::cout << ib.size() << std::endl;
} // here the destructor is called automatically even if an exception is thrown and the memory ib held is freed.
When an instance of int_buffer comes into existence it must have a size, and it will allocate the necessary memory. When it goes out of scope, it's destructor is called. This is very useful for things like synchronization objects. Consider
class mutex
{
// ...
take();
release();
class mutex::sentry
{
mutex & mm;
public:
sentry( mutex & m ) : mm(m)
{
mm.take();
}
~sentry()
{
mm.release();
}
}; // mutex::sentry;
};
mutex m;
int getSomeValue()
{
mutex::sentry ms( m ); // blocks here until the mutex is taken
return 0;
} // the mutex is released in the destructor call here.
Also, are there cases where you can't use RAII?
No, not really.
Do you ever find yourself wishing for garbage collection? At least a garbage collector you could use for some objects while letting others be managed?
Never. Garbage collection only solves a very small subset of dynamic resource management.
There are already a lot of good answers here, but I'd just like to add:
A simple explanation of RAII is that, in C++, an object allocated on the stack is destroyed whenever it goes out of scope. That means, an objects destructor will be called and can do all necessary cleanup.
That means, if an object is created without "new", no "delete" is required. And this is also the idea behind "smart pointers" - they reside on the stack, and essentially wraps a heap based object.
RAII is an acronym for Resource Acquisition Is Initialization.
This technique is very much unique to C++ because of their support for both Constructors & Destructors & almost automatically the constructors that are matching that arguments being passed in or the worst case the default constructor is called & destructors if explicity provided is called otherwise the default one that is added by the C++ compiler is called if you didn't write an destructor explicitly for a C++ class. This happens only for C++ objects that are auto-managed - meaning that are not using the free store (memory allocated/deallocated using new,new[]/delete,delete[] C++ operators).
RAII technique makes use of this auto-managed object feature to handle the objects that are created on the heap/free-store by explcitly asking for more memory using new/new[], which should be explicitly destroyed by calling delete/delete[]. The auto-managed object's class will wrap this another object that is created on the heap/free-store memory. Hence when auto-managed object's constructor is run, the wrapped object is created on the heap/free-store memory & when the auto-managed object's handle goes out of scope, destructor of that auto-managed object is called automatically in which the wrapped object is destroyed using delete. With OOP concepts, if you wrap such objects inside another class in private scope, you wouldn't have access to the wrapped classes members & methods & this is the reason why smart pointers (aka handle classes) are designed for. These smart pointers expose the wrapped object as typed object to external world & there by allowing to invoke any members/methods that the exposed memory object is made up of. Note that smart pointers have various flavors based on different needs. You should refer to Modern C++ programming by Andrei Alexandrescu or boost library's (www.boostorg) shared_ptr.hpp implementation/documentation to learn more about it. Hope this helps you to understand RAII.