2012-10-11 10 views
78

Gibt es einen anderen Unterschied zwischen throw() und noexcept abgesehen von überprüft Laufzeit und Kompilierzeit jeweils?Unterschied zwischen C++ 03 throw() - Spezifizierer C++ 11 noexcept

Wikipedia C++11 Artikel schlägt vor, dass C++ 03 Wurf Spezifizierer veraltet sind.
Warum ist noexcept fähig genug, um alles zur Kompilierzeit abzudecken?

[Anmerkung: I genannten this question und this article, konnte aber den festen Grund der deprecation nicht bekam.]

+6

Nach diesem [schönen Artikel] (http://akrzemi1.wordpress.com/2011/06/10/using-noexcept/) kann auch 'noexcept' Laufzeitüberprüfungen verursachen. Der Hauptunterschied zwischen ihnen ist, dass das Brechen von 'noexcept' 'std :: terminate' verursacht, während das Brechen von' throw' 'std :: unexpected' verursacht. Auch ein etwas anderes Stapelabwickelverhalten in diesen Fällen. – Fiktik

Antwort

101

Exception Bezeich wurden, weil exception specifiers are generally a terrible idea veraltet. noexcept wurde hinzugefügt, weil es die sinnvoll sinnvolle Verwendung eines Ausnahme-Spezifizierers ist: Wissen, wann eine Funktion nicht eine Ausnahme auslöst. So wird es eine binäre Wahl: Funktionen, die werfen werden und Funktionen, die nicht werfen werden.

noexcept wurde hinzugefügt, anstatt nur alle throw specifiers außer throw() zu entfernen, da noexcept leistungsfähiger ist. noexcept kann einen Parameter haben, dessen Kompilierungszeit in einen booleschen Wert aufgelöst wird. Wenn der Boolesche Wert wahr ist, bleibt der noexcept kleben. Wenn der Boolesche Wert falsch ist, bleibt der noexcept nicht haften und die Funktion kann werfen.

So können Sie etwas tun:

struct<typename T> 
{ 
    void CreateOtherClass() { T t{}; } 
}; 

Hat CreateOtherClass Wurf Ausnahmen? Es könnte, wenn der Standardkonstruktor T kann. Wie erzählen wir? Wie folgt aus:

struct<typename T> 
{ 
    void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; } 
}; 

So CreateOtherClass() wird werfen iff die Standard-Konstruktor angegebenen Typ wirft. Dies behebt eines der Hauptprobleme mit Ausnahmespezifizierern: ihre Unfähigkeit, den Aufrufstapel weiterzuleiten.

Sie können dies nicht mit throw() tun.

+0

+1 Nützliche Antwort, für mich sowieso. Immer noch auf der Suche nach einer Antwort, die besagt, warum ich 'noexcept' verwenden möchte. Ich habe '' throw() '- Spezifizierer nie benutzt und versuche zu bestimmen, ob 'noexcept' tatsächlich irgendeinen Nutzen bringt (außer der vom Compiler überprüften Dokumentation). – hmjd

+0

Gefunden gerade diese http://stackoverflow.com/questions/10787766/when-should-i-really-use-noexcept ... – hmjd

+0

@hmjd: "* Noch auf der Suche nach einer Antwort, die sagt, warum ich noexcept verwenden möchte . "Darauf wirst du keine Antwort finden, denn das ist * nicht die Frage *, die gestellt wurde. –

29

noexcept wird zur Kompilierzeit nicht überprüft.

Eine Implementierung darf einen Ausdruck nicht zurückweisen, nur weil er bei seiner Ausführung eine Ausnahme auslöst oder werfen könnte, die die enthaltene Funktion nicht zulässt.

Wenn eine Funktion, die noexcept oder throw() Versuche erklärt wird, eine Ausnahme ist der einzige Unterschied zu werfen, dass man terminate und die othe Anrufe unexpected und diese Art von Ausnahmebehandlung erfordert sind veraltet wirksam wurden.

1

std :: unexpected() wird von der C++ - Laufzeit aufgerufen, wenn eine dynamische Ausnahmespezifikation verletzt wird: Eine Ausnahme wird von einer Funktion ausgelöst, deren Ausnahmebedingung Ausnahmen dieses Typs verbietet.

std :: unexpected() kann auch direkt aus dem Programm aufgerufen werden.

In beiden Fällen ruft std :: unexcepted den aktuell installierten std :: unexpected_handler auf. Der Standard std :: unexpected_handler ruft std :: terminate auf.

Verwandte Themen