2016-09-10 5 views
2

Ich schrieb eine Klasse, die Lambda-Funktion darin speichern kann, um sicherzustellen, dass alle Ressourcen freigegeben werden, bevor eine Funktion beendet wird.Warum kann meine Vorlagenfunktion nicht inline sein

Ich teste meinen Code in MSVC2015, Release Modus mit /O2.

Allerdings finde ich, dass GenerateScopeGuard nicht inline sein kann und eine kleine Funktion generiert wird.

int main() 
{ 
01031C00 55     push  ebp 
01031C01 8B EC    mov   ebp,esp 
01031C03 51     push  ecx 
    auto func = GenerateScopeGuard([] {printf("hello\n"); }); 
01031C04 8D 4D FC    lea   ecx,[func] 
01031C07 E8 24 00 00 00  call  GenerateScopeGuard<<lambda_8b2f3596146f3fc3f8311b4d76487aed> > (01031C30h) 
    return 0; 
01031C0C 80 7D FD 00   cmp   byte ptr [ebp-3],0 
01031C10 75 0D    jne   main+1Fh (01031C1Fh) 
01031C12 68 78 61 03 01  push  offset string "hello\n" (01036178h) 
01031C17 E8 24 00 00 00  call  printf (01031C40h) 
01031C1C 83 C4 04    add   esp,4 
01031C1F 33 C0    xor   eax,eax 
} 
01031C21 8B E5    mov   esp,ebp 
01031C23 5D     pop   ebp 
01031C24 C3     ret 

    return ScopeGuard<T>(std::forward<T>(func)); 
01031C30 C6 41 01 00   mov   byte ptr [ecx+1],0 
01031C34 8B C1    mov   eax,ecx 
} 
01031C36 C3     ret 

Sieht aus wie Ausnahmebehandlung bezogen. In der Tat, wenn ich C++ Ausnahme deaktivieren, ist die Funktion inline, aber nicht mit /EHsc arbeiten. Warum?

Hier ist mein Code.

template<typename T> 
class ScopeGuard 
{ 
public: 
    ScopeGuard(const ScopeGuard&) = delete; 
    ScopeGuard& operator=(const ScopeGuard&) = delete; 

    explicit ScopeGuard(T&& func) : 
     func_(std::forward<T>(func)) 
    {} 

    ScopeGuard(ScopeGuard&& right) : 
     func_(std::move(right.func_)) 
    {} 

    ~ScopeGuard() 
    { 
     if (!dismissed_) func_(); 
    } 

    void Dismiss() 
    { 
     dismissed_ = true; 
    } 

private: 
    T func_; 
    bool dismissed_ = false; 
}; 

template<typename T> 
__forceinline ScopeGuard<T> GenerateScopeGuard(T&& func) noexcept 
{ 
    return ScopeGuard<T>(std::forward<T>(func)); 
} 

int main() 
{ 
    auto func = GenerateScopeGuard([] {printf("hello\n"); }); 
    return 0; 
} 
+1

Haben Sie keine Optimierung eingeschaltet? – Surt

+0

Und bitte geben Sie die volle Disass. Ist das Hinzufügen von 'Inline' oder sogar' Static' hilfreich? – edmz

+0

@Surt ja, kompiliere ich es mit/O2 – Nifury

Antwort

1

Es scheint, dass MSVC-Compiler durch die kürzlich eingeführte nicht statische Elementinitialisierungsfunktion verwirrt wird. Konstruktor mit Initialisierung scheint das Problem zu beheben:

ScopeGuard() 
    : dismissed_(false) 
{ 
} 
+0

Sie haben Recht! Obwohl es nicht mit MSVC2015 funktioniert, füge ich eine Memberfunktion zu init 'fledged_' hinzu und rufe es manuell nach der Konstruktion auf, um dieses Problem zu lösen. – Nifury

0

Kompilieren mit -O3 -std = C++ 14:

Ausgabe aus gcc 5.4:

.LC0: 
     .string "hello" 
main: 
     subq $8, %rsp 
     movl $.LC0, %edi 
     call puts 
     xorl %eax, %eax 
     addq $8, %rsp 
     ret 

Ausgabe von Klappern 3.8:

main:         # @main 
     pushq %rax 
     movl $.Lstr, %edi 
     callq puts 
     xorl %eax, %eax 
     popq %rcx 
     retq 

.Lstr: 
     .asciz "hello" 

Dies ist ohne das Nicht-Standard-Attribut __forceinline.

Sind Sie sicher, dass Sie die Optimierung aktiviert haben?

Wird diese Funktion generiert, aber nicht von main aufgerufen?

+0

Ja, ich kompiliere es mit/O2. Vielleicht ist es Compiler bezogen – Nifury

+0

@Nifury können Sie den Assembler-Code für die Funktion main ()? –

Verwandte Themen