Поведение исключения 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 это потенциально бросает.

Я сильно рекомендуем реструктуризировать код по порядку не чтобы бросить деструкторы.