c++ - 虚基类子对象之前是什么?

标签 c++

我的代码是:

class A { /* ... */ };
class B : virtual public A { /* ... */ };
class C : virtual public A { /* ... */ };

class X { /* ... */ };
class Y : virtual public X { /* ... */ };
class Z : virtual public X { /* ... */ };

class D : public B, public C, public Y, public Z {
public:
    __declspec(noinline) D() { printf("ctor in D\n"); }
    __declspec(noinline) virtual ~D() { printf("dtor in D\n"); }
};

int main()
{
    D *pd = new D;
    delete pd;
    return 0;
}

我发现在虚拟基类子对象之前有4个字节的空间。我不明白他们在做什么。

    delete pd;
00161D01  mov         eax,dword ptr [edi+4]  
00161D04  lea         ecx,[edi+4]  
00161D07  mov         eax,dword ptr [eax+4]  
00161D0A  add         ecx,eax  
00161D0C  push        1  
00161D0E  mov         eax,dword ptr [ecx]  
00161D10  call        dword ptr [eax+8]  
00161D13  pop         edi  

; call in delete goes here
00161D20  sub         ecx,dword ptr [ecx-4]                       ; <--
00161D23  jmp         D::`scalar deleting destructor' (0161C40h)  


__declspec(noinline) D() { printf("ctor in D, %d\n", &val_); }
00161A80  push        ebp  
00161A81  mov         ebp,esp  
00161A83  sub         esp,8  
00161A86  push        ebx  
00161A87  push        esi  
00161A88  mov         esi,ecx  
00161A8A  push        edi  
00161A8B  lea         ecx,[esi+28h]  
00161A8E  mov         dword ptr [ebp-8],0  
00161A95  mov         dword ptr [esi+4],163424h  
00161A9C  mov         dword ptr [esi+0Ch],1633F8h  
00161AA3  mov         dword ptr [esi+14h],1633F8h  
00161AAA  mov         dword ptr [esi+1Ch],163438h  
00161AB1  call        A::A (01616B0h)  
00161AB6  lea         ecx,[esi+30h]  
00161AB9  call        X::X (01618A0h)  
00161ABE  push        ecx  
00161ABF  mov         ecx,esi  
00161AC1  call        B::B (0161740h)  
00161AC6  push        ecx  
00161AC7  lea         ecx,[esi+8]  
00161ACA  call        C::C (01617F0h)  
00161ACF  push        ecx  
00161AD0  lea         ecx,[esi+10h]  
00161AD3  call        Y::Y (0161920h)  
00161AD8  push        ecx  
00161AD9  lea         ecx,[esi+18h]  
00161ADC  call        Z::Z (01619D0h)  
00161AE1  mov         edx,esi  
00161AE3  mov         dword ptr [esi+8],163394h  
00161AEA  mov         eax,dword ptr [edx+4]  
00161AED  mov         dword ptr [edx],1633F0h  
00161AF3  mov         dword ptr [esi+10h],16338Ch  
00161AFA  mov         dword ptr [esi+18h],163414h  
00161B01  mov         eax,dword ptr [eax+4]  
00161B04  mov         dword ptr [eax+edx+4],163404h  
00161B0C  mov         eax,dword ptr [edx+4]  
00161B0F  mov         eax,dword ptr [eax+8]  
00161B12  mov         dword ptr [eax+edx+4],1633E4h  
00161B1A  mov         eax,dword ptr [edx+4]  
00161B1D  mov         ecx,dword ptr [eax+4]  
00161B20  lea         eax,[ecx-24h]  
00161B23  mov         dword ptr [ecx+edx],eax                      ; <--
00161B26  mov         eax,dword ptr [edx+4]  
00161B29  mov         ecx,dword ptr [eax+8]  
00161B2C  lea         eax,[ecx-2Ch]  
00161B2F  mov         dword ptr [ecx+edx],eax                      ; <--
00161B32  lea         eax,[edx+20h]  
00161B35  push        eax  
00161B36  push        163318h  
00161B3B  call        dword ptr ds:[16303Ch]  
; ...


    __declspec(noinline) virtual ~D() { printf("dtor in D\n"); }
00161BB0  push        ebx  
00161BB1  push        esi  
00161BB2  push        edi  
00161BB3  mov         edi,ecx  
00161BB5  push        163370h  
00161BBA  mov         eax,dword ptr [edi-24h]  
00161BBD  mov         dword ptr [edi-28h],1633F0h  
00161BC4  mov         dword ptr [edi-20h],163394h  
00161BCB  mov         dword ptr [edi-18h],16338Ch  
00161BD2  mov         dword ptr [edi-10h],163414h  
00161BD9  mov         eax,dword ptr [eax+4]  
00161BDC  mov         dword ptr [eax+edi-24h],163404h  
00161BE4  mov         eax,dword ptr [edi-24h]  
00161BE7  mov         eax,dword ptr [eax+8]  
00161BEA  mov         dword ptr [eax+edi-24h],1633E4h  
00161BF2  mov         eax,dword ptr [edi-24h]  
00161BF5  mov         ecx,dword ptr [eax+4]  
00161BF8  lea         eax,[ecx-24h]  
00161BFB  mov         dword ptr [ecx+edi-28h],eax                  ; <--
00161BFF  mov         eax,dword ptr [edi-24h]  
00161C02  mov         edx,dword ptr [eax+8]  
00161C05  lea         eax,[edx-2Ch]  
00161C08  mov         dword ptr [edx+edi-28h],eax                  ; <--
00161C0C  call        dword ptr ds:[16303Ch]  
00161C12  add         esp,4  
00161C15  lea         ecx,[edi-8]  
00161C18  call        Z::~Z (0161A20h)  
; ...

在构造函数和析构函数中,该值为0。减去的值正好是到虚拟基类子对象的偏移量。

VS2012, Release模式。

最佳答案

vtordisp !使用 #pragma vtordisp( off ) 来避免它

关于c++ - 虚基类子对象之前是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18428388/

相关文章:

c++ - 修改命令行参数

c++ - 使用模板元编程实现 std::all_of 的静态版本?

c++ - 从 Windows 10 上的 Visual Studio 2015 链接 libpqxx

c++ - 在 Windows 上构建 Gstreamer 1.0.5

c++ - 使用 std::enable_if 元函数在模板类中重载运算符 +=

c++ - 使用继承重载 = 运算符

c++ - 如何在cuda中生成伪随机数

c++ - 将 Kinect 深度图像转换为真实世界坐标

C++模板函数多重实例化

c++ - 在 TTreeView 上点击 TListView(在 TForm 上)触发 TTreeView OnChange 事件