2012-09-13 20 views
5

Con el código siguiente, ¿puede un compilador decir que a es de hecho una instancia de B y optimizar la búsqueda de la tabla virtual?Optimización de las búsquedas de tabla virtual

#include <iostream> 

class A 
{ 
    public: 
    virtual void f() 
    { 
     std::cout << "A::f()" << std::endl; 
    } 
}; 

class B : public A 
{ 
    public: 
    void f() 
    { 
     std::cout << "B::f()" << std::endl; 
    } 
}; 

int main() 
{ 
    B b; 
    A* a = &b; 
    a->f(); 

    return 0; 
} 

pregunta adicional después de que las respuestas de Jonthan Seng y Reima: En caso se utiliza gcc, ¿sería necesario utilizar ninguna bandera para forzarlo a optimizar las operaciones de búsqueda vtable?

+0

La única manera de saber con certeza es mirar a la asamblea. Pero sí, la desvirtualización es una optimización estándar del compilador. – Mysticial

+0

Acaba de agregarse el desmontaje para GCC. Usé la bandera '-O1' para optimizaciones básicas. – reima

Respuesta

5

Clang puede hacer fácilmente esta optimización, e incluso indica la llamada a la función. Esto puede ser visto desde el conjunto generado:

Dump of assembler code for function main(): 
    0x0000000000400500 <+0>: push %rbp 
    0x0000000000400501 <+1>: mov %rsp,%rbp 
    0x0000000000400504 <+4>: mov $0x40060c,%edi 
    0x0000000000400509 <+9>: xor %al,%al 
    0x000000000040050b <+11>: callq 0x4003f0 <[email protected]> 
    0x0000000000400510 <+16>: xor %eax,%eax 
    0x0000000000400512 <+18>: pop %rbp 
    0x0000000000400513 <+19>: retq 

he tomado la libertad de reemplazar std::cout << … por llamadas equivalentes a printf, ya que esto reduce en gran medida el desorden en el desmontaje.

GCC 4.6 también se puede deducir que no es necesaria ninguna consulta de vtable, pero no lo hace en línea:

Dump of assembler code for function main(): 
    0x0000000000400560 <+0>: sub $0x18,%rsp 
    0x0000000000400564 <+4>: mov %rsp,%rdi 
    0x0000000000400567 <+7>: movq $0x4007c0,(%rsp) 
    0x000000000040056f <+15>: callq 0x400680 <B::f()> 
    0x0000000000400574 <+20>: xor %eax,%eax 
    0x0000000000400576 <+22>: add $0x18,%rsp 
    0x000000000040057a <+26>: retq 
+0

+1 Visual Studio 2010 también lo desvirtualiza. Pero no lo alinea. – Mysticial

+0

Tengo solo gcc 4.4 por el momento. No parece para optimizar las operaciones de búsqueda, incluso con -O3: subQ \t $ 24,% RSP .cfi_def_cfa_offset 32 ​​ movq \t $ _ZTV1B + 16, (RSP%) movq \t% RSP,% RDI llamada \t * _ZTV1B 16 (% RIP) xorl \t% eax,% eax addq \t $ 24, RSP% .cfi_def_cfa_offset 8 ret – Ruup

+1

Atorníllelo! ¡Simplemente no puedo formatearlo! – Ruup

-2

Tal vez pueda, eso dependería de la inteligencia del compilador y de los requisitos de optimización.

Pero esta es una llamada. ¿Por qué te importa optimizar esta única llamada? Y, si te importa, ¿por qué no solo obtener el tipo correcto para esta llamada?

La primera respuesta a todas las preguntas sobre la optimización es: "¿Por qué necesita optimizar eso?" Haga que un informe de la herramienta de rendimiento indique que el 50% del tiempo de la solicitud es un lugar y la pregunta es respondida. "Ah, pero es ineficiente", la respuesta más común, conduce a un código que no se puede mantener y que rara vez optimiza el código que es realmente ineficiente.

+1

No perdoné, pero si al OP no le importó, esta pregunta no se habría hecho. – Mysticial

+2

A menudo, las personas se preocupan por la optimización cuando no hay ninguna razón para hacerlo. Entonces, voy a hacer una pregunta de eso. –

+0

La respuesta habría estado en los comentarios, entonces ... –

Cuestiones relacionadas