我的代码是:
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,发布模式。