The notions of resource management and invariants allow us to formulate the basic exception safety guarantee of the C++ standard library. Simply put, we can't consider any class exception safe unless it has an invariant and maintains it even when exceptions occur. Furthermore, we can't consider any piece of code to be exception-safe unless it properly releases all resources it acquired.
Thus, the standard library provides this guarantee:
- Basic guarantee for all operations: The basic invariants of the standard library are maintained, and no resources, such as memory, are leaked.
The standard library further defines these guarantees:
Strong guarantee for key operations: In addition to providing the basic guarantee, either the operation succeeds, or has no effects. This guarantee is provided for key library operations, such as push_back(), and single-element insert() on a list.
Nothrow guarantee for some operations: In addition to providing the basic guarantee, some operations are guaranteed not to throw an exception. This guarantee is provided for a few simple operations, such as swap() and freeing memory.
These concepts are invaluable when thinking about exception safety. Trying to add enough try-blocks to a program to deal with every problem is simply too messy, too complicated, and can easily lead to inefficient code. Structuring code as described earlier, with the aim of providing the strong guarantee where possible and the basic guarantee always, is easier and leads to more maintainable code. Note that the Vector::operator=() actually provides the strong guarantee. Often the strong guarantee comes naturally when you try not to delete an old representation before you've constructed a new one. The basic guarantee is used more when you're optimizing code to avoid having to duplicate information.