2014-11-11 8 views
11

Hier ist, was wirtry {....} catch (..) nur dann, wenn eine bestimmte Kompilierung Ausdruck wahr ist

try { 
    std::uninitialized_copy(...); 
} catch(...) { 
    if(!boost::has_trivial_destructor<T>::value) { 
     // some cleanup to do here... 
    } 
    throw; 
} 

Wir fragen uns, ob die try/catch hat Kosten zu tun versuchen, wenn Die Kompilierzeitkonstante in if ist falsch.

Kann der Compiler innerhalb seiner "as-if" -Rechte den try catch entfernen und sich so verhalten, als ob der std::uninitialized_copy Aufruf ohne try um ihn herum erschienen wäre?

Oder ist in den C++ - Spezifikationen etwas versteckt, das den Compiler benötigt, um es hier zu lassen? Stellen Sie sich als Beispiel eine hypothetische surrounding_try_blocks()-Funktion vor, die die dynamische umgebende Anzahl von try-Blöcken um einen Frame zurückgibt.

+0

Könnten Sie bitte Ihre question.Like erarbeiten, wenn Sie „sagen, tut try/catch mit Kosten verbunden ist ... "Welche Kosten meintest du? Lediglich das Setzen von Try/Catch-Blöcken hat einige Performance-Kosten. – ravi

+0

Wenn ich die Frage verstehe, dann ist es: if 'boost :: ...'ist wahr, dann könnte der Code bis auf den Aufruf von 'unitialized_copy' optimiert werden, da er nur eine Exception abfängt und sie dann erneut auslöst. Aber darf ein Compiler diese Optimierung vornehmen? – Tommy

+0

Wenn der Compiler die if-Anweisung optimiert, funktioniert Ihr Programm genauso wie ohne die try/catch-Blöcke, nein? Ich sehe also nicht, welchen Overhead der Compiler für die Optimierung hätte. –

Antwort

0

Im Folgenden habe ich die Kosten für die Verwendung der Ausnahme zusammengefasst, die ich aus verschiedenen Quellen zusammengestellt habe. Was du in deinem zweiten Punkt fragst, ist mir nicht sehr klar. Also dachte ich, es wäre besser, alles durchzugehen. Hoffe, du würdest etwas von deiner Wichtigkeit auswählen.

Um Ausnahmen zur Laufzeit zu behandeln, müssen Programme eine beträchtliche Menge an Buchhaltung führen. Sie müssen an jedem Punkt während der Ausführung in der Lage sein, die Objekte zu identifizieren, die zerstört werden müssen, wenn eine Ausnahme ausgelöst wird. sie müssen jeden Ein- und Ausgang eines Versuchsblocks notieren; und für jeden try-Block müssen sie die zugehörigen catch-Klauseln und die Arten von Ausnahmen, die diese Klauseln verarbeiten können, verfolgen.

Es gibt Dinge, die Sie bezahlen, auch wenn Sie keine Ausnahmebehandlungsfunktionen verwenden. Sie bezahlen den Speicherplatz, der von den Datenstrukturen benötigt wird, um zu verfolgen, welche Objekte vollständig aufgebaut sind, und zahlen Sie für die Zeit, die benötigt wird, um diese Datenstrukturen auf dem neuesten Stand zu halten. Diese Kosten sind normalerweise ziemlich bescheiden.

Trotzdem ohne Unterstützung kompilierte Programme für Ausnahmen sind sowohl der Regel schneller und kleiner als ihre Pendants mit Unterstützung

Ausnahmen zusammengestellt
+4

Aber das beantwortet die Frage nicht. "Kann der Compiler innerhalb seiner" as-if "-Rechte den try-catch entfernen und sich so verhalten, als ob der' std :: uninitialized_copy'-Aufruf ohne "try" um ihn herum erschienen wäre? ". Mit anderen Worten, kann die gesamte Arbeit, die Sie beschreiben, eliminiert werden, da der Compiler (im Prinzip) sehen kann, dass er nicht benötigt wird? –

0

Von 15,1/8 finden wir

Ein Wurf-Ausdruck ohne Operand rethrows die derzeit gehandhabte Ausnahme (15.3). Die Ausnahme wird mit dem vorhandenen temporär reaktiviert; kein neues temporäres Ausnahmeobjekt wird ... erstellt klar für mich

diesen ziemlich impliziert, dass die Bewertung des boost::has_trivial_destructor<T>::value unter der Annahme, kann trivialerweise keine Nebenwirkungen haben, gezeigt wird, dass der Compiler in der Lage sein soll, dass die gesamte Masse leicht, um zu bestimmen Der Catch ist nicht ausführbar und das gesamte Konstrukt kann weg optimiert werden. Mir ist kein Compiler bekannt, der dies jedoch tut/tut.

Mein einziger (geringfügiger) Zweifel ist, ob die Sprache das Löschen und Zurücksetzen von std::uncaught_exception() in die "as-if" -Klausel fallen lässt.

1

Ich habe keine Ahnung, was der Compiler tun, aber ich weiß, dass Sie die Optimierung von selbst durchsetzen können:

template <class T> 
typename boost::enable_if_t<boost::has_trivial_destructor<T>::value, void> 
wrap_uninitialized_copy (...) { 
    std::uninitialized_copy(...); 
} 

template <class T> 
typename boost::enable_if_t<!boost::has_trivial_destructor<T>::value, void> 
wrap_uninitialized_copy (...) { 
    try { 
     std::uninitialized_copy(...); 
    } catch(...) { 
     // some cleanup to do here... 
     throw; 
    } 
}