2010-05-03 14 views
12

Kann jemand Exception Specifications wie in C++ verwendet erklären?Kann mir jemand C++ - Ausnahme-Spezifikationen erklären?

  • Wenn sie verwendet werden (ich habe es selten in Code verwendet gesehen)
  • Was sind die Vor- und Nachteile (Vorteile/Nachteile) von Ausnahme-Spezifikationen verwendet?
+4

Der endgültige Artikel auf Ausnahme Spezifikationen: http://www.gotw.ca/publications/mill22.htm „Moral # 1:. Außer möglicherweise eine leere, aber wenn ich: Nie eine Ausnahme Spezifikation Moral # 2 schreiben Du würdest mir sogar das meiden. " –

+0

http://www.gotw.ca/publications/mill22.htm –

+1

Nachricht aus der Zukunft: wenn jemand das heute liest, sollte man wissen, dass 'noexcept' Programmleistung verbessern kann (in C++ 11) –

Antwort

15

Wann sind sie verwendet (ich habe es selten in Code verwendet gesehen)
Hoffentlich nie, wie sie in der nächsten Version von C++ sind veraltet aufgrund der Standardisierung im nächsten Jahr.

Was sind die Vor- und Nachteile (Vorteile/Nachteile) der Verwendung von Ausnahmenspezifikationen?
Sie bieten eine Möglichkeit für Leser Ihres Codes, genau zu wissen, welche Ausnahmen eine Funktion auslösen darf. Das Problem ist, dass wenn eine unerwartete Ausnahme (eine nicht in der Spezifikation) geworfen wird, das Programm beendet wird (standardmäßig).

+0

@James McNellis: Danke :) –

-3

Grundsätzlich ermöglichen Exception-Spezifikationen dem Compiler, den Stack zu optimieren. Der Nachteil ist, dass es eine verdammt viel Extra-Spezifikation ist. Dies bedeutet, dass Sie es häufig in der Bibliotheksarbeit sehen, aber nicht so sehr in funktionierendem Code.

Ich glaube es gibt auch einige Kompilierungs-Exception-Sicherheit Sache, aber da ich es nie benutzt habe, kann ich nicht sicher sein.

+0

-1 : Exception-Spezifikationen haben absolut nichts mit dem Stack zu tun. –

+1

http://msdn.microsoft.com/en-us/library/7f10tsf4(v=VS.80).aspx Ich denke, dass, wenn wir abwickelbar Objekte diskutieren, die nichts mit dem Stapel zu tun haben. – Puppy

+0

Exception-Spezifikationen _can_ erlauben eine Compiler-Optimierung des generierten Codes; eine leere Ausnahmespezifikation (d. h. "throw()") kann es dem Compiler ermöglichen, bestimmten ansonsten notwendigen Code auf der Grundlage der Garantie des Programmierers, dass die Funktion keine Ausnahme auslöst, wegzulassen. Wie sehr es hilft, ich habe keine Ahnung; Ich glaube ehrlich gesagt nicht, dass ich jemals eine Ausnahme-Spezifikation in meinem Code geschrieben habe. –

12

Sie werden allgemein als eine schlechte Idee betrachtet.

Sie sagen, was eine Methode werfen wird. Der Nachteil ist, dass wenn diese Methode etwas anderes auslöst, die App beendet wird. Es ist also eine Garantie, aber nicht so, wie Java es tut. Und es fügt den Overhead der Inspektion hinzu.

+3

+1: Aber Nitpick: Die Anwendung wird nicht beendet; die unerwartete Funktion wird aufgerufen. Standardmäßig bedeutet dies, dass Ihre App beendet wird, aber wenn Sie die unerwartete Funktion haben, die etwas anderes als das tut, wird etwas anderes passieren. –

+0

+1 Throw-Spezifikationen sind veraltet, aber leider nicht in C++ 0x entfernt. @ Billy: +1 für die Erklärung. Ich habe zwei Beispiele, an die ich denken kann, wo eine No-Throw-Spezifikation wünschenswert ist: Destruktoren und Funktionen/Methoden, von denen bekannt ist, dass sie Sprache/Interop-Grenzen überschreiten, da C++ - Ausnahmen nicht gut mit anderen spielen. (und ich bin mir bewusst, dass C++ 0x besagt, dass No-Throw-Spezifikationen geändert werden und dass die aktuelle Syntax veraltet ist). –

+1

@Billy: Die unerwartete Funktion kann zuerst eine Fehlermeldung ausgeben, aber muss sie das Programm nicht beenden? IIRC Es ist verboten, von unerwarteten() zurückzukehren. –

6

Die wichtige Sache zu wissen ist: Ausnahmespezifikationen sind in der nächsten Version von C++ veraltet, mit Ausnahme des No-throw-Spezifizierers (throw()), der im Grunde genommen offiziell sagt "verwende sie nicht".

Das Setzen von throw() nach einer Funktion bedeutet, dass die Funktion keine Ausnahmen auslöst. Wenn dies trotzdem der Fall ist, wird die Anwendung beendet (wahrscheinlich wird der unerwartete Handler aufgerufen), so dass der Rest Ihrer Anwendung diese Funktion verwenden kann, obwohl sie weiß, dass sie keine Ausnahme auslöst. Dies ist praktisch, um ausnahmesicheren Code zu schreiben.

Beispiel:

void MyFunction() throw() // does not throw any exceptions 
{ 
    /* ... */ 
{ 
+3

Die No-Throw-Garantie ist sehr wichtig. Besonders für Destruktoren. Es wäre aber nett, wenn der Compiler Sie warnen würde, dass Sie eine No-Throw-Methode haben, die potenziell werfen könnte. –

+1

Beachten Sie, dass 'throw()' die Spezifikation der dynamischen Ausnahme angibt, während 'noexcept' die Überprüfung der Kompilierzeit angibt und Optimierungen zulässt.Wenn Methode als 'throw()' markiert ist, bedeutet das nicht, dass sie nicht geworfen werden kann, so dass der Compiler trotzdem einige Ausnahmen erzeugen muss. Und in dem Fall mit "noexcept" kann es einfach nicht. Der Compiler generiert keinen redundanten Code für Ausnahmen und lässt Sie keine Funktion kompilieren, die einige Ausnahmen (oder irgendwelche aufgerufenen Funktionen, die in ihn geworfen werden) auslöst und mit "noexcept" gekennzeichnet ist. –

+0

@Occulta Ich bin mir ziemlich sicher, dass eine Funktion, die mit 'noexcept' gekennzeichnet ist, immer noch eine Ausnahme auslösen kann. – Navin

1

Sie den Programmierer angeben, welche Ausnahmen von dieser Funktion geworfen werden. Sie haben den Vorteil, dass Sie die Garantie haben, dass keine anderen Ausnahmen von dieser Funktion ausgelöst werden können. Es wird jedoch nicht zur Kompilierungszeit überprüft, ob die Funktion tatsächlich Ausnahmen auslöst, die nicht in dem throw-Spezifizierer angegeben sind. Stattdessen wird es zur Laufzeit überprüft. Und wenn es fehlschlägt, dann wird unexpected() aufgerufen, die standardmäßig abort() aufruft, die wiederum Ihr Programm standardmäßig beendet. Also, es sei denn, du willst wirklich, dass dein Programm stirbt, wenn du versagst und eine unerwartete Ausnahme ausgelöst wird, ist es wahrscheinlich eine schlechte Idee, sie zu benutzen.

Der einzige Ort, wo ich sie tatsächlich empfehlen würde, ist auf Destruktoren. Es ist wirklich schlecht, wenn ein Destruktor wirft. Sie sollten niemals werfen.Wenn Sie also throw() für einen Destruktor verwenden, um anzuzeigen, dass keine Ausnahme ausgelöst werden kann, wissen Sie, dass Ihr Programm lieber stirbt, als im schlechten Zustand weiterzumachen, in dem es sich befindet, nachdem eine Ausnahme von einem Destruktor ausgelöst wurde.

Unabhängig davon, ob Sie jede Art von throw Spezifizierer verwenden, müssen Sie sicher sein, dass Sie es wirklich wollen Ihr Programm sterben, wenn verletzt wird. Also, allgemein gesprochen, ist es am besten, sie nicht zu benutzen.

Verwandte Themen