2016-10-06 5 views
6

In C++ ist der folgende CodeC++: Kann "versuchen {foo();} fangen (...) {werfen;}" auf "foo();" optimiert werden?

try { 
    foo(); 
} catch (...) { 
    throw; 
} 

semantisch identisch mit nur foo wie diese nennen?

foo(); 

Wenn ja, kann ich eine state-of-the-art-Compiler erwarten, dass die erste Version auf der zweiten Version zu vermeiden (wenn mit Optimierung kompilieren aktiviert)?

Mit anderen Worten, wenn ich kompilieren diesen Code mit NDEBUG und Optimierungen aktiviert

try { 
    foo(); 
} catch (...) { 
    assert(some_check()); 
    throw; 
} 

kann ich davon ausgehen, dass es nie langsamer sein sollte, dass dieses hässliche Version

#ifndef NDEBUG 
    try { 
#endif 
    foo(); 
#ifndef NDEBUG 
    } catch (...) { 
    assert(some_check()); 
    throw; 
    } 
#endif 
+2

[Nicht in der Praxis.] (Https://godbolt.org/g/kXdxf6) – Veedrac

+0

Ich rate nur hier, aber wenn nichts in foo() eine Ausnahme auslöst, kann man davon ausgehen, dass der Compiler das machen kann Optimierung. – DeiDei

+2

@DeiDei Wenn 'foo' nicht geworfen werden kann (und der Compiler das weiß, zB durch' noexcept'), wird der Compiler alle zugehörigen Exception-Handling-Zweige entfernen. Aber die Frage ist allgemeiner. – Veedrac

Antwort

3

Nein, die beiden sind nicht gleichwertig.

Ob der Stapel abgewickelt wird, wenn es keinen Handler für eine Ausnahme gibt, ist implementierungsdefiniert ([except.handle] p9). Wenn ein Handler vorhanden ist, aber die Ausnahme nur erneut auslöst, muss der Stapel mindestens bis zum Punkt, an dem die Ausnahme erneut ausgelöst wird, abgewickelt werden.

Das heißt:

struct S { ~S(); }; 
void foo() { S s; throw 0; } 
int main() { 
    try { foo(); } 
    catch(...) { throw; } 
} 

Dies muss s ‚s destructor nennen. Wenn die try { ... } catch (...) { throw; } entfernt wird, ist es nicht länger erforderlich, den Destruktor s aufzurufen.

Es ist sogar möglich, je nachdem, was s ‚s destructor tat, die für die Ausführung nie den Wieder Werfen der Ausnahme zu erreichen, durch Zugabe von zB:

#include <stdlib.h> 
S::~S() { exit(0); } 

Jetzt muss das Programm erfolgreich ausgeführt, aber wenn die try { ... } catch (...) { throw; } entfernt wird, ist das nicht mehr erforderlich, und ein Absturz kann und geschieht auf echten Systemen.

Verwandte Themen