2012-11-14 12 views
8

Viene visualizzato uno strano problema in cui i metodi dei membri non vengono allineati se si definisce un distruttore.La definizione di un distruttore impedisce che le funzioni membro siano in linea

codice Esempio:

#include <cstdio> 

class Foo 
{ 
public: 
    Foo(int arg) : data(arg) {} 
    ~Foo(void) {} 

    Foo bar(void) const { return Foo(7); } 

    int data; 
}; 

int main(void) 
{ 
     Foo a(3); 
     Foo b = a.bar(); 

     printf ("%i", b.data); 
} 

Se si utilizza il distruttore di default, ottengo qualcosa di simile:

main: 
sub   rsp,28h 
lea   rcx,[string "%i" (013FB8ADA0h)] 
mov   edx,7 
call  printf (013FB81068h) 
xor   eax,eax 
add   rsp,28h 
ret 

Ma se io definisco il mio distruttore vuoto, come nel codice qui sopra:

Foo::bar: 
mov   dword ptr [rdx],7 
mov   rax,rdx 
ret 

main: 
sub   rsp,28h 
lea   rdx,[b] 
call  Foo::bar (013FA11000h) 
mov   edx,dword ptr [b] 
lea   rcx,[string "%i" (013FA1ADA0h)] 
call  printf (013FA11088h) 
xor   eax,eax 
add   rsp,28h 
ret 

Compilato come versione di rilascio utilizzando Visual Studio 2012 (v110), anche se ha provato anche Visual Studio 2010 (v100). Ho provato a impostare/Ob2 per convincerlo a incorporare il metodo senza fortuna.

Non ho familiarità con l'assemblaggio per sapere esattamente cosa sta cercando di fare, forse domani cercherò di capirlo per vedere se fornisce qualche suggerimento. Qualcuno può far luce sul motivo per cui la definizione di un distruttore vuoto impedirebbe che il metodo sia in linea?

EDIT [17/11/2012]

Ho aggiornato il codice sopra per essere molto più semplice (in origine stavo lavorando sulla mia classe Vector).

Il ritorno di un tipo primitivo da un metodo membro sembra essere eseguito correttamente, è solo un problema quando restituisco un'istanza della mia classe.

+0

La mia soluzione è stata utile? –

risposta

2

Visual Studio tratta classi con distruttori (vuoto o meno) come "complesso" e saranno più propensi ad abbandonare alcune ottimizzazioni. Se la tua classe è semplice e sensibile alla velocità, usa il distruttore predefinito.

+0

Per espandere la risposta, il seguente articolo MSDN [inline, __inline, __forceinline] (http://msdn.microsoft.com/en-us/library/z8y1yy88 (v = vs.71) .aspx) spiega che il compilatore non può inlineare una funzione se * la funzione restituisce un oggetto non riavviabile per valore, quando compilato con/GX,/EHs o /EHa.* Sembra che il mio oggetto sia definito come non modificabile in quanto ha un distruttore definito dall'utente (anche anche se è vuoto). Disattivando i flag "Abilita eccezioni C++" è possibile ricomporre nuovamente l'oggetto. – Gareth

+0

NB. Restituire un riferimento (all'oggetto) consente anche di essere in linea. – Gareth

0

In VS 2010 sembra che il compilatore calcoli il valore finale in fase di compilazione e lo carichi nello stack per il valore di a.
Modifica del codice come di seguito ha fatto attivare questa ottimizzazione con distruttore definito:

inline void operator = (const __m128 v) 
{ 
    data = v; 
} 

inline __m128 operator* (const Vector4& a) const 
{ 
    return _mm_mul_ps(data, a.data); 
} 
+0

Non risponde completamente perché il compilatore non sta integrando il metodo, anche se lo userò sicuramente quando lavoro sulla mia classe Vector, poiché mi piace questo approccio. – Gareth

Problemi correlati