Terminate вызывается после выброса экземпляра исключения, ядро сброшено

Я перехожу через C++ исключения и сталкиваюсь с ошибкой, в которой я не уверен, почему это вызывает у меня проблемы:

 #include <iostream>
 #include <exception>

 class err : public std::exception
 {
 public:
      const char* what() const noexcept { return "error"; }
 };

 void f() throw()
 {
      throw err();
 }

 int main()
 {
      try
      {
           f();
      }
      catch (const err& e)
      {
           std::cout << e.what() << std::endl;
      }
 }

Когда я запускаю его, я получаю следующую ошибку во время выполнения:

 terminate called after throwing an instance of 'err'
   what():  error
 Aborted (core dumped)

Если я переместить логику try/catch полностью в f(), т.е.

 void f() 
 {
      try
      {
           throw err();
      }
      catch (const err& e)
      {
            std::cout << e.what() << std::endl;
      }
 }

И просто вызвать его из main (без блока try/catch в main), тогда ошибки нет. Я что-то не понимаю, поскольку это связано с генерацией исключений из функций?

Ответ 1

throw() в void f() throw() является спецификацией динамического исключения и устарела начиная с С++ 11. Предполагалось, что он будет использован для перечисления исключений, которые может выдать функция. Пустая спецификация (throw()) означает, что нет никаких исключений, которые ваша функция могла бы выбросить. Попытка вызвать исключение из такой функции вызывает std::unexpected который по умолчанию завершается.

Начиная с С++ 11 предпочтительный способ указать, что функция не может генерировать, это использовать noexcept. Например, void f() noexcept.