I think that of all the features of C++, destructors are probably my favorite. They seem simple enough (code that is run when an object is destroyed, ensuring resources are cleaned up) but when you look into the consequences of that, they change the entire game and mean that C++, while it looks at first glance quite similar to C, is a very different language altogether.
RAII gets talked about a lot but the real meat of it is RRID - the destruction part.
For one thing, they mean that some things can now happen implicitly, rather than having to be explicitly coded. That's a good thing - it means the higher-level code can be terser and terser code is less likely to contain bugs. A common complaint of C programmers learning C++ for the first time is that they can't see exactly what's going on by looking at the code any more - but what they haven't yet realized is that that is a good thing.
For another thing, they make exceptions possible, with all the benefits they bring, and without the overhead, non-orthogonality and non-determinism of garbage collection.
Because destructors are not like normal functions, there are some things that you should not do with them (like throw exceptions from them). One way to think about this is that normal functions (including constructors) do "forward" work and destructors to "reverse" work (undoing things, releasing resources etc.). The reverse work should never be able to fail because that means that neither forward progress nor reverse progress can be made - it means the program is irretrievably broken and must be terminated immediately. Hacks like uncaught_exception() should not be used - if you're tempted to use it is a sign that you're trying to make forward progress in a destructor and that you should re-think your design.
Another way of writing "reverse direction" code in some languages is "finally". It's too bad that C++ doesn't have this (you either have to catch and rethrow or write a special object) - there are occasions when you want to do some one-off cleanup and don't want to have to write a whole class just to get a destructor, and the "finally" notation makes it clearer than the catch/rethrow notation. I wouldn't give up destructors for finally, though, as some languages do.