Skip to content
C++ Basics: Restore State with a Small Scope Guard

C++ Basics: Restore State with a Small Scope Guard

November 2, 2026

Use a noncopyable destructor-based guard to restore a flag even when an exception leaves the scope.

Prepare a scratch directory

Tested on Linux x86_64 with GCC 14.2.0. Install a C++20-capable GCC compiler and its standard-library development files, with g++ on PATH. You also need Bash, a text editor, and mktemp, rm, and rmdir. No third-party library is required.

Keep the same terminal open. Stop if setup fails before saving the source:

start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1

Run the example

Save this as scope-restoration-guard-demo.cpp:

#include <iostream>
#include <stdexcept>

class RestoreFlag {
public:
    explicit RestoreFlag(bool& target) noexcept
        : target_(target), previous_(target)
    {
        target_ = true;
    }
    ~RestoreFlag() noexcept { target_ = previous_; }
    RestoreFlag(const RestoreFlag&) = delete;
    RestoreFlag& operator=(const RestoreFlag&) = delete;
private:
    bool& target_;
    bool previous_;
};

int main()
{
    bool processing = false;
    std::cout << std::boolalpha;
    try {
        RestoreFlag restore_processing(processing);
        std::cout << "Inside: " << processing << '\n';
        throw std::runtime_error("simulated failure");
    } catch (const std::runtime_error&) {
        std::cout << "After exception: " << processing << '\n';
    }
}

Compile and run it. The second command runs only after compilation succeeds:

g++ -std=c++20 -Wall -Wextra -Werror -pedantic scope-restoration-guard-demo.cpp -o scope-restoration-guard-demo &&
./scope-restoration-guard-demo

Observed output:

Inside: true
After exception: false

Read the result

The guard captures the previous flag value before enabling it. Stack unwinding destroys the guard when the exception leaves the try block, restoring the original value before the catch block runs. Deleted copy operations prevent multiple guards accidentally representing the same restoration action.

Apply it carefully

The referenced flag must outlive the guard. The destructor only assigns a bool and cannot throw. A production resource guard should similarly release its resource without throwing during unwinding. Prefer standard ownership and locking classes for resources they already support. Destructors do not provide cleanup after every abnormal termination, and this flag is not a thread-synchronization mechanism.

The C++ working draft documents the relevant behavior. This example uses C++20 features, not newer additions shown elsewhere in the current draft.

Clean up

Remove only the source and executable created here, then remove the empty practice directory:

rm -- scope-restoration-guard-demo.cpp scope-restoration-guard-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directory

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on