Avoiding virtual tables in polymorphic classes

According to this page , the Microsoft extended attribute __declspec(novtable)"stops the compiler from generating code to initialize vfptr in the constructor (s) and the class destructor ... Using this __declspec form can significantly reduce code size."

I compiled the following code with an update to Visual Studio 2013 4, release configuration, x64, and I got the assembler code shown after.

struct __declspec(novtable) textEmpty
{
    virtual void fs() = 0;
};

struct textEmpty2
{
    virtual void fs() = 0;
};

struct Y : textEmpty
{
    void fs() override;
};

void Y::fs()
{
    wcout << sizeof( * this ) << endl;
}

struct Y2 : textEmpty2
{
    void fs() override;
};

void Y2::fs()
{
    wcout << sizeof( * this ) << endl;
}

int main()
{
    Y * d_ = new Y;
    Y2 * d_2 = new Y2;
    d_->fs();
    d_2->fs();
    return 0;
}
    Y * d_ = new Y;
mov         ecx,8
call        operator new (07FF7AEED1090h)
test        rax,rax
je          main+26h (07FF7AEEA2A66h)
lea         rdx,[Y::`vftable' (07FF7AEF189B0h)]
mov         qword ptr [rax],rdx
    Y2 * d_2 = new Y2;
mov         ecx,8
call        operator new (07FF7AEED1090h)
lea         rcx,[Y2::`vftable' (07FF7AEF189C0h)]
test        rax,rax
cmove       rcx,qword ptr [rax]
mov         qword ptr [rax],rcx

Question 1 . I calculate the same number of instructions in both constructors. In light of Microsoft claims to __declspec(novtable)reduce code size, did I miss something?

2. Y2 * d_2 = new Y2;, RCX, . RCX . , ?


UPDATE , /O 2. , . .

/GS/GL/W3/Gy/Zc: wchar_t/Zi/Gm-/O2/sdl/Fd "x64\Release\vc120.pdb" /fp: exact/D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /errorReport: prompt/WX-/Zc: forScope/Gd/Oi/MT/Fa "x64\Release \" /EHsc/nologo/Za/Fo "x64\Release \"

+4
1

. ...

β„–1:

__ declspec (novtable) , , , :

vtable, , , , . __declspec .

, . :

struct __declspec(novtable) textEmpty {
    virtual void fs() {};
};
struct textEmpty2 {
    virtual void fs() {};
};
struct Y : textEmpty {
    void fs() override;
};
void Y::fs() {
    wcout << sizeof(*this) << endl;
}
struct Y2 : textEmpty2 {
    void fs() override;
};
void Y2::fs()     {
    wcout << sizeof(*this) << endl;
}
int main() {
    textEmpty* e = new textEmpty;
    textEmpty2* e2 = new textEmpty2;
    Y * d_ = new Y;
    Y2 * d_2 = new Y2;
    d_->fs();
    d_2->fs();
    return 0;
}

:

    textEmpty* e = new textEmpty;
000000013FFB12BA  mov         ecx,8  
000000013FFB12BF  call        qword ptr [__imp_operator new (013FFB3178h)]  
    textEmpty2* e2 = new textEmpty2;
000000013FFB12C5  mov         ecx,8  
000000013FFB12CA  call        qword ptr [__imp_operator new (013FFB3178h)]  
000000013FFB12D0  test        rax,rax  
000000013FFB12D3  je          main+2Fh (013FFB12DFh)  
000000013FFB12D5  lea         rcx,[textEmpty2::`vftable' (013FFB3348h)]  
000000013FFB12DC  mov         qword ptr [rax],rcx  
    Y * d_ = new Y;
000000013FFB12DF  mov         ecx,8  
000000013FFB12E4  call        qword ptr [__imp_operator new (013FFB3178h)]  
000000013FFB12EA  mov         rdi,rax  
000000013FFB12ED  test        rax,rax  
000000013FFB12F0  je          main+4Eh (013FFB12FEh)  
000000013FFB12F2  lea         rax,[Y::`vftable' (013FFB32F0h)]  
000000013FFB12F9  mov         qword ptr [rdi],rax  
000000013FFB12FC  jmp         main+50h (013FFB1300h)  
000000013FFB12FE  xor         edi,edi  
    Y2 * d_2 = new Y2;
000000013FFB1300  mov         ecx,8  
000000013FFB1305  call        qword ptr [__imp_operator new (013FFB3178h)]  
000000013FFB130B  mov         rbx,rax  
000000013FFB130E  test        rax,rax  
000000013FFB1311  je          main+6Fh (013FFB131Fh)  
000000013FFB1313  lea         rax,[Y2::`vftable' (013FFB3300h)]  
000000013FFB131A  mov         qword ptr [rbx],rax  
000000013FFB131D  jmp         main+71h (013FFB1321h)  
000000013FFB131F  xor         ebx,ebx  
? new novtable, textEmpty, vftable pointer. , , novtable, vftable pointer.

β„– 2:

- - . :

/GS/GL/W3/Gy/Zc: wchar_t/Zi/Gm-/O2/Fd "x64\Release\vc120.pdb" /fp: /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /errorReport: prompt/WX-/Zc: forScope/Gd/Oi /MD/Fa "x64\Release \" /EHsc/nologo/Fo "x64\Release \" /Fp "x64\Release\sotestaaa.pch"

cmove , :

test        rax,rax
cmove       rcx,qword ptr [rax]

 if (rax == 0) mov rcx, [rax]

, . , rax == 0 (.. New 0). rax 0, .

, VS 2013 (12.0.21005.1 REL) .

, . novtable , . novtable , . new NULL, vftable ( ).

, , ++ fs() d d_2 , , d d_2 :

d:

  mov         rdi,rax

d_2:

  mov         rbx,rax 
+2

All Articles