C++如何自动调用析构函数?

Posted

技术标签:

【中文标题】C++如何自动调用析构函数?【英文标题】:How does C++ automatically call destructor? 【发布时间】:2018-02-06 23:11:13 【问题描述】:

在C++中,我们可以通过对象来管理资源,即在Ctor中获取资源,在Dtor中释放(RAII)。这依赖于 C++ 的自动析构函数调用。但这是如何在幕后完成的呢?例如,C++ 如何知道为c1 而不是c2 调用Dtor。 (我知道这之前一定已经回答过了,但我所有的搜索都以解释如何使用 RAII 的主题结束)。谢谢!

class Cat;
Cat c1;
Cat* c2 = new Cat();

编辑: 我知道我需要为c2 调用删除。我只是不明白当c1 超出范围时如何调用 Dtor。

【问题讨论】:

GCC 是免费软件,Clang 是开源的。去看看吧。 它已经完成,因为 C++ 标准说它必须完成。它是通过让你的 C++ 编译器生成符合 C++ 标准的编译代码来完成的。 编译器将其添加到程序集中。 c2 也调用了析构函数,只是不是Cat 析构函数而是Cat* 析构函数,这是微不足道的。 @rozina Calling ~int() 【参考方案1】:

看看compiler explorer。我已经链接了您示例的可构建版本。以防万一链接不是永久性的,如果这个答案,我已经复制了最后的代码。

对于Cat c1; 行(浅红色),您会看到asm 中有三个对应的块,颜色相同。

lea rax, [rbp-28]
mov rdi, rax
call Cat::Cat()

这与堆栈上对象的构造相匹配。

接下来是

lea rax, [rbp-28]
mov rdi, rax
call Cat::~Cat()

这是正常的返回路径,自动调用析构函数。

终于有了

lea rax, [rbp-28]
mov rdi, rax
call Cat::~Cat()
mov rax, rbx
mov rdi, rax
call _Unwind_Resume

这是抛出异常时采用的路径(例如,new)。它会自动调用析构函数,然后继续异常。

为了完整起见,这里是C++源代码:

    class Cat
    
    public:
        Cat() : meow() 
        ~Cat() 
    private:
        int meow;
    ;

    void foo()
    
        Cat c1;
        Cat* c2 = new Cat();
    

    int main()
    
        foo();    
    

【讨论】:

+1 用于编译器资源管理器。特别是因为您可以轻松地将更复杂的控制流添加到代码中,并查看生成的析构函数调用如何移动。

以上是关于C++如何自动调用析构函数?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 类设计总结回顾------析构函数

C++ 析构函数何时被调用?

C++ 析构函数何时被调用?

Java:在范围退出时自动调用函数(如 c++ 析构函数)

c++ delete 调用析构函数问题。

c++中,析构函数和delete各有啥作用啊