为什么我的程序集输出中有两个析构函数实现? [英] Why do I have two destructor implementations in my assembly output?

查看:123
本文介绍了为什么我的程序集输出中有两个析构函数实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

objdump揭示了我对于同一类有两个不同的析构函数.为什么?

And objdump of my .o file reveals that I have two different destructors for the same class. Why?

Disassembly of section .text._ZN1AD0Ev:

0000000000000000 <_ZN1AD0Ev>:
   0:   53                      push   %rbx
   1:   be 00 00 00 00          mov    $0x0,%esi
   6:   48 89 fb                mov    %rdi,%rbx
   9:   48 c7 07 00 00 00 00    movq   $0x0,(%rdi)
  10:   ba 2c 00 00 00          mov    $0x2c,%edx
  15:   bf 00 00 00 00          mov    $0x0,%edi
  1a:   e8 00 00 00 00          callq  1f <_ZN1AD0Ev+0x1f>
  1f:   48 89 df                mov    %rbx,%rdi
  22:   be 08 00 00 00          mov    $0x8,%esi
  27:   5b                      pop    %rbx
  28:   e9 00 00 00 00          jmpq   2d <_ZN1AD0Ev+0x2d>

Disassembly of section .text._ZN1AD2Ev:

0000000000000000 <_ZN1AD1Ev>:
   0:   48 c7 07 00 00 00 00    movq   $0x0,(%rdi)
   7:   ba 2c 00 00 00          mov    $0x2c,%edx
   c:   be 00 00 00 00          mov    $0x0,%esi
  11:   bf 00 00 00 00          mov    $0x0,%edi
  16:   e9 00 00 00 00          jmpq   1b <_ZN1AD1Ev+0x1b>

这些是头文件中的类,这些类导致生成此代码:

These are the classes in the header file that result in this code being generated:

#include <iostream>

class A {
 public:
   virtual ~A() {
      ::std::cout << "This destructor does something significant.\n";
   }
};

class B : public A {
 public:
   inline virtual ~B() = 0;
};

B::~B() = default;

class C : public B {
 public:
   inline virtual ~C() = default;
};

推荐答案

许多编译器会为一个类生成两个不同的析构函数:一个用于销毁动态分配的对象,另一个用于销毁非动态对象(静态对象,本地对象,基本对象).子对象或成员子对象).前者从内部调用operator delete,后者则不.有些编译器通过向一个析构函数添加一个隐藏参数来做到这一点(旧版本的GCC这样做,MSVC ++这样做),有些编译器仅生成两个单独的析构函数(新版的GCC这样做).

Many compilers generate two different destructors for one class: one for destroying dynamically allocated objects, another - for destroying non-dynamic objects (static objects, local objects, base sub-objects or member sub-objects). The former calls operator delete from inside, the latter doesn't. Some compilers do it by adding a hidden parameter to one destructor (older versions of GCC do it that way, MSVC++ does it that way), some compilers simply generate two separate destructors (newer versions of GCC do it that way).

从析构函数内部调用operator delete的需要源于C ++规范,该规范要求应仿佛"选择适当的operator delete,就像从最派生的析构函数内部(可能是虚拟的)析构函数中查找它一样.目的.因此,可以作为 static 成员函数实现的operator delete的行为应类似于 virtual 函数.

The need to call operator delete from inside the destructor arises from C++ specification, which says that the proper operator delete should be chosen "as if" it was looked up from inside the (possibly virtual) destructor of the most derived object. So, operator delete, which can be implemented as a static member function should behave as if it were a virtual function.

大多数实现都是从字面上实现此要求的:它们不仅从析构函数内部查找适当的operator delete,而且实际上从那里调用.

Most implementations implement this requirement "literally": they not only look up the proper operator delete from inside the destructor, they actually call it from there.

当然,只有从最派生的对象的析构函数中调用operator delete,并且仅当该对象是动态分配的时才调用.这是隐藏参数(或两个析构函数的版本)进入图片的地方.

Of course, operator delete only has to be called from the most derived object's destructor, and only if that object was dynamically allocated. This is where that hidden parameter (or two versions of destructor) come into the picture.

这篇关于为什么我的程序集输出中有两个析构函数实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆