> Automatic destructor calls on leaving scope is the nicest part of c++ - shame it interacts with exceptions so nastily that nobody understands how it works. "Exception safe code" yeah, right, not in c++.
OK, I think I figured out what this was referring to. Generally a constructor initializes an object, and the destructor undoes all of that work. If a constructor throws an exception before it completes, the destructor is never called. This is a common interview question, because it surprises people. But there's no way for the compiler to figure out which parts of the destructor must be run (to clean up things that completed successfully) and which parts must not be run (because they refer to things that were never initialized).
The solution to the problem, amusingly, is to create more destructors. It's trivial to run the destructor for any objects that were created as part of an object's construction, so the compiler does promise to do that. To make this concrete, if a Foo object has members of types Bar and a Baz, and the Foo constructor also creates a temporary Quux and opens a network connection, throwing an exception from Foo's constructor will cause any successfully-created Bars, Bazes and Quuxes to be destroyed, but the network connection won't be closed because the compiler doesn't know that close_connection() must be called for every successful open_connection(). But if you wrap those open_connection()/close_connection() calls in an RAII object, you can guarantee that they'll be cleaned up correctly.
OK, I think I figured out what this was referring to. Generally a constructor initializes an object, and the destructor undoes all of that work. If a constructor throws an exception before it completes, the destructor is never called. This is a common interview question, because it surprises people. But there's no way for the compiler to figure out which parts of the destructor must be run (to clean up things that completed successfully) and which parts must not be run (because they refer to things that were never initialized).
The solution to the problem, amusingly, is to create more destructors. It's trivial to run the destructor for any objects that were created as part of an object's construction, so the compiler does promise to do that. To make this concrete, if a Foo object has members of types Bar and a Baz, and the Foo constructor also creates a temporary Quux and opens a network connection, throwing an exception from Foo's constructor will cause any successfully-created Bars, Bazes and Quuxes to be destroyed, but the network connection won't be closed because the compiler doesn't know that close_connection() must be called for every successful open_connection(). But if you wrap those open_connection()/close_connection() calls in an RAII object, you can guarantee that they'll be cleaned up correctly.