Thanks Peter for that informative answer.
One unmentioned fact is that the exception mechanism in C++ is designed to allow for implementations to have zero runtime cost. Basically exception handlers can be found by matching the stack frames with tables, and registers can be populated using basically debug info.
How this is done is at the ABI level, but the Itanium C++ ABI, which is the one used for x86-* does this.
http://mentorembedded.github.io/cxx-abi/abi-eh.html
An interesting nugget I learned today reading up on the ABI is that the ABI actually supports common lisp conditions, that is, restarting or continuing a computation that is in an exceptional state is supported by the ABI, but not by C++. I don't know of any language that supports zero-overhead exceptions and conditions, but the support is already standardized. It isn't unthinkable that some C++ implementation would have extensions to hook into the exception handling mechanism before stack-unwinding happens.