Поведение исключения C++14 vs C++98
Я написал следующую программу
#include <iostream>
#include <stdexcept>
class Myclass
{
public:
~Myclass()
{
//throw std::runtime_error("second (in destructor)");
throw 1;
}
};
void fun()
{
Myclass obj;
}
int main()
{
try
{
fun();
}
catch (const std::exception& e)
{
std::cout << e.what();
}
catch(...)
{
std::cout << " ... default Catch" << std::endl;
}
std::cout << "Normal" << std::endl;
return 0;
}
когда я запускаю выше программы C++98
режим (cpp.sh) он печатает
... default Catch
Normal
когда я запускаю его с C++14
режим, он ничего не печатает. почему такое поведение меняется?
Я понимаю, что всякий раз, когда возникало какое-либо исключение и любое destructor
(в процессе раскручивания стека) выдает любое исключение, оно завершает приложение. Но здесь только одно исключение от try
блок, который с destructor
.
2 ответов
начиная с C++11 деструктор без явно прописанной спецификации исключения имеет ту же спецификацию исключения, что и сгенерированная по умолчанию. В вашем случае деструктор, созданный по умолчанию, будет noexcept
(большинство деструкторов по умолчанию), поэтому ваш деструктор считается noexcept
Как хорошо. Метание изnoexcept
функция автоматически называет std::terminate
.
если вы хотите, чтобы исключение было уловимым, объявите деструктор как метание:
~Myclass() noexcept(false)
{
//throw std::runtime_error("second (in destructor)");
throw 1;
}
но прежде чем вы это сделаете, пересмотреть. это плохая идея иметь метательные деструкторы.
выбрасывание исключений из деструкторов всегда плохая идея, так как, если уже есть исключение в полете (например, деструктор, вызываемый во время размотки стека) std::terminate
будет называться.
тем не менее, C++11 добавил неявное noexcept(true)
деструкторам (кроме случаев, перечисленных ниже), и это снова означает std::terminate
Если бросать с noexcept(true)
деструктор.
§12.4/3
[класс.dtor] [ Примечание: объявление деструктора, который не имеет noexcept-спецификатор имеет то же исключение спецификация как будто была неявно объявлена (15.4). - конец Примечания ]
и §15.4/14
[за исключением.спекуляция] Спецификация исключения для неявно объявленного деструктора или деструктора без спецификатора noexcept, потенциально-бросать, если и только если любой из деструкторы для любых потенциально построены subojects это потенциально бросает.
Я сильно рекомендуем реструктуризировать код по порядку не чтобы бросить деструкторы.