Hard15 minC++ Fundamentals
UpdatedAug 4, 2026
Edit

Exception Safety Guarantees

CONCEPTS:C++ Exception Safety

Question Variations

  • "What are the basic and strong exception guarantees?"
  • "How does RAII make code exception-safe?"
  • "When should a move operation be `noexcept`?"
  • "Why should destructors normally not throw?"

Why This Is Asked

Exception safety distinguishes code that merely compiles from code that maintains resource and state invariants under failure. Interviewers use this topic to assess your use of RAII, transaction-like updates, and noexcept boundaries.

Key Concepts

  • The no-throw guarantee means an operation never throws.
  • The strong guarantee means an operation either succeeds or has no observable effect.
  • The basic guarantee preserves valid invariants and avoids leaks, but state may change.
  • RAII releases resources during stack unwinding.

Question Variations

  • “What are the basic and strong exception guarantees?”
  • “How does RAII make code exception-safe?”
  • “When should a move operation be noexcept?”
  • “Why should destructors normally not throw?”

Answers by Technology

+ Add Variant
C++Improve this answer ✏️

Expected Answer (C++23)

Exception safety describes what an operation guarantees if it throws. The basic guarantee leaves all objects valid and avoids resource leaks, though observable state may have changed. The strong guarantee is transactional: the operation either completes or leaves state unchanged. The no-throw guarantee promises no exception escapes.

RAII provides the foundation: local guards and owning objects clean up while the stack unwinds. For a strong guarantee, perform fallible work first and commit a non-throwing state change only after it succeeds.

#include <string>
#include <utility>

class Profile {
public:
    void set_name(std::string name) {
        // Construction of the parameter happens before the function body.
        // Swapping two std::strings is non-throwing.
        name_.swap(name);
    }

private:
    std::string name_;
};

If construction of the argument fails, name_ is unchanged. Once in the function, the non-throwing swap commits the update.

Why It Matters

Clear guarantees preserve invariants in the face of allocation, I/O, and user-code failures. They make libraries safer to compose and prevent half-applied updates that are difficult to recover from.

Common Mistakes

  • Manually releasing resources only on success: An exception skips that cleanup; use RAII guards.
  • Throwing from a destructor during stack unwinding: A second active exception causes std::terminate.
  • Marking a function noexcept without enforcing it: If it throws, the program terminates rather than propagating an error.

Follow-up Questions

  • Why does std::vector care whether a move constructor is noexcept? (Answer: It can use a non-throwing move during reallocation while preserving its strong guarantee.)
  • What is the basic guarantee? (Answer: No resource leaks and all objects remain valid, though their state may have changed.)