【问题标题】:How does C++ automatically call destructor?C++如何自动调用析构函数?
【发布时间】: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()

标签: c++ raii


【解决方案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 用于编译器资源管理器。特别是因为您可以轻松地将更复杂的控制流添加到代码中,并查看生成的析构函数调用如何移动。
猜你喜欢
  • 1970-01-01
  • 2020-04-10
  • 2014-05-03
  • 2012-03-18
  • 2016-10-09
  • 2021-07-19
  • 1970-01-01
  • 2017-04-28
  • 2014-05-17
相关资源
最近更新 更多