Suppose I'm a teacher and I want to explain to my students what are the benefits of using RAII in C++: I need a very good example, full of details, but that is easy to understand.
Which approach would you use?
There's the classic opening and closing of a file. Using RAII the main flow of the algorithm will be clear without getting cluttered up with lots of try/finally-close logic littering the landscape.
Besides the clarity it provides to the code (separating clean up from core logic), there is the safety. If you have database you want to make sure connections are taken from the pool as LATE as possible. And returned to the pool as SOON as possible. Without RAII there is a high chance that someone could accidentally hang on to a connection somewhere. This increases the chance the pool will be empty and things will blow up. On a system with high user volume this is serious.
Safety and clarity.
EDIT: Oh, almost forgot. It also lends it self very well to reverse-order clean up. As a rule-of-thumb you generally want to clean stuff up in the reverse order you obtained it. For example if you are at a bank, you open the door, then open the safe. At the end of the day you want to close the door of the safe before you close the door to the bank (like a stack). Since RAII is literally controlled by the stack it is a natural fit for reverse-order clean up via scoping.
RAII is just so darn elegant. In my opinion it is the "answer" to resource clean up. Unlike a garbage collector it appropriate for more than just memory. Unfortunately not many programmers understand it; both old-school and new-school.
I would think one way to convey the notion is by example. Implement a class that requires some resource that is likely to fail at times. Opening a file that may not exist or something similar. First implement it without using RAII, then show how all the error handling code just disappears when using RAII sensibly.
The reduced complexity of the code using RAII should make the benefits quite obvious I think.
The benefit to RAII is ultimately encapsulation, in that once you've created an object you no longer need to worry about what to do with it once you've finished using it.
So, if you have a class that opens a file handle, you can make whatever operations you like on that object (which affects the underlying file) and when you destroy the object, you no longer have to think "do I have to close the file handle" or "is the file handle closed yet". Its gone, dealt with, fully automatically handled for you. And that magic happens because of RAII.
So you can compare RAII to C-style manual memory management, where you'd open a file, pass the handle around to various functions, and then have to remember to pass the handle to a close_file() function. You can compare it to 'coffee'-style garbage collection manual object management, where you'd create an object that opens a file, perform operations on the object and then have to remember to call dispose or wrap your object in a using block to make the dispose method run - and have to put special code in your finaliser to clear it up as well.
And then you can show the C++ way where you don't have to remember to do anything at all, it just magically works for you, right there and then (so if you suddenly have to re-open the file, it's not locked by an object that is waiting to be garbage collected).
PS. Herb Sutter's talk at Build about modern C++ features has a section on RAII, starting at 13:50 minutes in where he shows a comparison between C-style code and C++ RAII code.
RAII is used in several places in the standard library. It's useful to see clear examples used by the standard. Good examples include any of the iostream classes, fstream, sstream, etc. Even auto_ptr (or now unique_ptr) demonstrate RAII for memory situations.