Конструктор копирования класса исключения

Я проверяю, как выбрасывать при выполнении вызовов раскрутки стека std::terminate имея конструктор копирования класса, который используется для броска, броска.

Согласно C ++ 14 N4296 — §15.1.3:

Вызов исключительной копии инициализирует (8.5, 12.8) временный объект,
называется объектом исключения. Временный является lvalue и используется для
инициализировать переменную, объявленную в соответствующем обработчике (15.3).

class X
{
public:

X() = default;

X(const X&)
{
throw std::runtime_error{"X copy constructor"};
}
};

int main()
{
try
{
throw X{};
}
catch(const std::exception& e)
{
std::cout << e.what() << std::endl; // this line gets executed, does not terminate
}
catch(const X& other)
{
std::cout << "X exception" << std::endl;
}
}

Почему вышеприведенный код не вызывает std::terminate? В моем понимании приведенного выше кода throw X{} внутри try, запускает перемотку стека, а затем вызывается конструктор копирования для вызова обработчика, но также выдает конструктор копирования. Как примечание, если измените выражение броска конструктора копирования для throw X{} тогда это заканчивается.

4

Решение

Пока объект исключения не был инициализирован, исключение еще не было выдано. И, таким образом, система не начала выполнять обработку исключений.

Поскольку копия выбрасывает, и это то, что инициализирует объект исключения, единственным throw который успешно выполняется — тот, что в конструкторе копирования.

Как примечание, если изменить выражение throw конструктора копирования на throw X {}, то оно завершается.

Это фактически переполнение стека из-за бесконечной рекурсии. Каждая попытка создания объекта исключения вызывает еще одно исключение и еще одну попытку создания объекта исключения.

4

Другие решения

Других решений пока нет …