2013-02-07 16 views
15

Supponiamo che io ho il seguente codiceI compilatori C++ possono ottimizzare le chiamate di funzioni virtuali ripetute sullo stesso puntatore?

void f(PolymorphicType *p) 
{ 
    for (int i = 0; i < 1000; ++i) 
    { 
     p->virtualMethod(something); 
    } 
} 

volontà del compilatore codice generato dereferenziare p s' vtable voce per virtualMethod 1 o 1000 volte? Sto usando il compilatore di Microsoft.

modificare

Ecco l'assembly generato per il caso del mondo reale che sto guardando. line->addPoint() è il metodo di preoccupazione virtuale. Non ho esperienza di assemblaggio, quindi lo sto esaminando lentamente ...

; 369 :  for (int i = 0; i < numPts; ++i) 

    test ebx, ebx 
    je SHORT [email protected]_SCANNE 
    lea edi, DWORD PTR [ecx+32] 
    npad 2 
[email protected]_SCANNE: 

; 370 :  { 
; 371 :   double *pts = pPoints[i].SystemXYZ; 
; 372 :   line->addPoint(pts[0], pts[1], pts[2]); 

    fld QWORD PTR [edi+8] 
    mov eax, DWORD PTR [esi] 
    mov edx, DWORD PTR [eax+16] 
    sub esp, 24     ; 00000018H 
    fstp QWORD PTR [esp+16] 
    mov ecx, esi 
    fld QWORD PTR [edi] 
    fstp QWORD PTR [esp+8] 
    fld QWORD PTR [edi-8] 
    fstp QWORD PTR [esp] 
    call edx 
    add edi, 96     ; 00000060H 
    dec ebx 
    jne SHORT [email protected]_SCANNE 
[email protected]_SCANNE: 

; 365 :  } 
+5

Chiedere al compilatore di generare codice assembler e controllare. –

+1

Compilalo con ottimizzazioni e guarda il codice generato risultante. – Petesh

+3

Per aggiungere al commento di Joachim - * non c'è altro modo * per scoprire altro che controllare. –

risposta

5

In generale, no, non è possibile. La funzione potrebbe distruggere *this e posizionare-nuovi alcuni altri oggetti derivati ​​dalla stessa base in quello spazio.

Modifica: ancora più semplice, la funzione potrebbe cambiare solo p. Il compilatore non può sapere chi ha l'indirizzo di p, a meno che non sia locale all'unità di ottimizzazione in questione.

2

Impossibile in generale, ma ci sono casi speciali che possono essere ottimizzati, in particolare con l'analisi inter-procedurale. VS2012 con le ottimizzazioni pieno e l'ottimizzazione intero programma viene compilato questo programma:

#include <iostream> 

using namespace std; 

namespace { 
struct A { 
    virtual void foo() { cout << "A::foo\n"; } 
}; 

struct B : public A { 
    virtual void foo() { cout << "B::foo\n"; } 
}; 

void test(A& a) { 
    for (int i = 0; i < 100; ++i) 
    a.foo(); 
} 
} 

int main() { 
    B b; 
    test(b); 
} 

a:

01251221 mov   esi,64h 
01251226 jmp   main+10h (01251230h) 
01251228 lea   esp,[esp] 
0125122F nop 
01251230 mov   ecx,dword ptr ds:[1253044h] 
01251236 mov   edx,12531ACh 
0125123B call  std::operator<<<std::char_traits<char> > (012516B0h) 
01251240 dec   esi 
01251241 jne   main+10h (01251230h) 

in modo che sia efficace ottimizzato il ciclo per:

for(int i = 0; i < 100; ++i) 
    cout << "B::foo()\n"; 
+0

più 1 per l'ottimizzazione dell'intero programma/link-time, il che rende l''impossibile' spesso banalmente possibile. –

Problemi correlati