在Visual Studio中缺少析构函数?

时间:2017-07-10 11:34:27

标签: c++ visual-studio exception-handling language-lawyer destructor

我写了以下程序:

// Example program
#include <iostream>
#include <string>
#include <exception>

struct A {
    A() {
        std::cout << "A ctor" << std::endl;

    }

    ~A() { 
        std::cout << "A dtor" << std::endl;
        try {
            throw std::exception();
        } catch (std::exception &e) {
            std::cout << "Internal exception caught" << std::endl;
        }
    }
};

int main()
{
    try {
        A a;
        throw std::exception();
    } catch (std::exception &e) {
        std::cout << "External exception caught" << std::endl;
    }
}

我预期的输出是:

A ctor
A dtor
Internal exception caught
External exception caught

这就是我在GCC中获得的。但是,当我使用Visual Studio(2013版)时,我得到的输出是:

A ctor
External exception caught

这里发生了什么?

1 个答案:

答案 0 :(得分:10)

MSVC2013 在这里是错误的, GCC 是对的。不幸的是,我现在无法从标准中找到合适的参考,但根据std::uncaught_exception

  

例如,如果堆栈展开导致堆栈分配的对象   destructed,该对象的析构函数可以运行抛出的代码   只要异常被某个catch块捕获就会出现异常   在逃避析构函数之前。

有关详细信息,另请参阅“在堆栈展开期间投掷”部分here

最后,正如@StoryTeller所提到的,对于较新的MSVC版本,此行为无法重现。

我能找到的最接近的标准是下一个(来自N3936草案):

  

15.1抛出异常[except.throw]

     
      
  1. 如果是异常处理机制,完成后   初始化异常对象但在激活之前   异常的处理程序,调用通过一个退出的函数   异常,调用std :: terminate。
  2.   

因此,正式地说,在堆栈展开过程(包括析构函数)中调用一个可能处理异常的函数是完全有效的,但是如果这个函数中的异常没有被适当的catch块捕获那么{{必须要调用1}}。