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

6
在C++中,我们可以通过对象来管理资源,即在Ctor中获取资源,并在Dtor中释放资源(RAII)。这依赖于C++的自动析构函数调用。但是,在底层如何实现呢?例如,C++如何知道要调用c1的Dtor而不是c2的Dtor。(我知道这个问题以前肯定已经回答过了,但我的所有搜索结果都是关于如何使用RAII的主题)。谢谢!
class Cat;
Cat c1;
Cat* c2 = new Cat();

编辑: 我知道需要为c2调用delete,但我不明白当c1超出范围时如何调用Dtor。

Note: "Dtor" refers to the destructor of an object.

1
GCC是自由软件,Clang是开源的。去了解一下吧。 - StoryTeller - Unslander Monica
4
这样做是因为C++标准规定必须这样做。实现的方法是让你的C++编译器生成符合C++标准的已编译代码。 - Sam Varshavchik
2
编译器将其添加到汇编中。 - Brandon
4
也会调用 c2 的析构函数,只不过是调用 Cat* 的析构函数,这个析构函数是微不足道的。 - Hatted Rooster
1
@rozina 调用 ~int() - Caleth
显示剩余12条评论
1个回答

13

请看编译器探索器。我已经链接了您示例的可构建版本。以防链接不是永久的,我已将代码复制到此答案的末尾。

对于Cat c1;这一行(浅红色),您将看到汇编中有三个相应的块,颜色相同。

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();    
    }

2
+1 for编译器探索者。特别是因为你可以轻松地将更复杂的控制流程添加到代码中,并查看生成的析构函数调用如何移动。 - ComicSansMS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接