2012-11-14 12 views
8

Widzę dziwny problem, w którym metody elementów nie są wprowadzane, jeśli zdefiniuję destruktor.Definiowanie destruktora uniemożliwia wstawianie funkcji składowych

Przykładowy kod:

#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); 
} 

przypadku korzystania z domyślnego destruktora, mam coś takiego:

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

Ale jeśli zdefiniować własną pustego destruktor, jak w powyższym kodzie:

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 

Skompilowany jako kompilacja wydania przy użyciu programu Visual Studio 2012 (v110), ale również wypróbowany Visual Studio 2010 (v100). Próbowałem ustawić/Ob2, aby pomóc przekonać go do wstawienia metody bez powodzenia.

Nie jestem dostatecznie zaznajomiony z montażem, aby wiedzieć dokładnie, co próbuje zrobić, może jutro spróbuję to rozgryźć, aby zobaczyć, czy daje jakieś wskazówki. Czy ktokolwiek może rzucić jakiekolwiek światło na to, dlaczego zdefiniowanie pustego destruktora uniemożliwiłoby wstawienie metody?

EDYCJA [17/11/2012]

Zaktualizowałem powyższy kod, aby był znacznie prostszy (pierwotnie pracowałem nad moją klasą Vector).

Zwracając typ prymitywny z metody elementu, wydaje się, że jest poprawnie wstawiony, jest to tylko problem, gdy zwracam instancję mojej klasy.

+0

było moje pomocne rozwiązanie? –

Odpowiedz

2

Visual Studio traktuje zajęcia z destruktorów (pusta czy nie) jako „kompleks” i będą one bardziej prawdopodobne, aby porzucić pewne optymalizacje. Jeśli twoja klasa jest prosta i wrażliwa na szybkość, użyj domyślnego destruktora.

+0

Aby rozwinąć odpowiedź, następujący artykuł MSDN [inline, __inline, __forceinline] (http://msdn.microsoft.com/en-us/library/z8y1yy88 (v = vs.71) .aspx) wyjaśnia, że ​​kompilator nie może wstawić funkcji, jeśli * funkcja zwraca obiekt rozwijany według wartości, gdy kompilowany z/GX,/EHs lub/EHa.* Wydaje się, że mój obiekt jest zdefiniowany jako unwindable, ponieważ ma zdefiniowany przez użytkownika destruktor (nawet choć jest pusty). Wyłączenie flag "Enable C++ Exceptions" pozwala na ponowne wpisanie obiektu. – Gareth

+0

NB. Zwrócenie odwołania (do obiektu) pozwala również na jego wstawienie. – Gareth

0

W VS 2010 wygląda na to, że kompilator oblicza końcową wartość w czasie kompilacji i po prostu ładuje ją do stosu o wartości a.
Modyfikowanie jak poniższy kod nie włączyć tę optymalizację z destruktora zdefiniowane:

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

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

Nie odpowiada całkowicie na pytanie, dlaczego kompilator nie stosuje metody, ale zdecydowanie użyję tego podczas pracy z moją klasą Vector, ponieważ podoba mi się to podejście. – Gareth

Powiązane problemy