Gibt es in C++ einen Unterschied zwischen „throw“ und „throw ex“?

Lesezeit: 5 Minuten

Gibt es in C einen Unterschied zwischen „throw und „throw
Joshua Fox

Diese Frage würde ich gerne stellen (auch hier), aber diesmal zu C++.

Was ist der Unterschied in C++ zwischen

try { /*some code here*/}
catch(MyException& ex)
{ throw ex;} //not just throw

und

try {  /*some code here*/}
catch(MyException& ex)
{ throw;} //not throw ex

Liegt es nur am Stacktrace (was in C++ sowieso kein Standard ist wie in C# oder Java)?

(Wenn es einen Unterschied macht, verwende ich MSVS 2008.)

  • throw ex; // out of apartment

    – Fredoverflow

    14. August ’12 um 11:27

  • @sehe, mein Fehler, ich habe den Punkt total verfehlt.

    – Charles D Pantoga

    9. Oktober ’13 um 2:01

Gibt es in C einen Unterschied zwischen „throw und „throw
Naveen

throw; wirft dasselbe Ausnahmeobjekt erneut aus, das es währenddessen abgefangen hat throw ex; löst eine neue Ausnahme aus. Es macht keinen Unterschied, außer aus Performancegründen, ein neues Ausnahmeobjekt zu erstellen. Wenn Sie eine Ausnahmehierarchie haben, von der einige andere Ausnahmeklassen abgeleitet sind MyException -Klasse und beim Auslösen einer Ausnahme haben Sie Folgendes getan: throw DerivedClassException; es kann von der gefangen werden catch(MyException&). Wenn Sie nun dieses abgefangene Ausnahmeobjekt ändern und mit erneut auslösen throw; der Typ des Ausnahmeobjekts wird weiterhin sein DerivedClassException. Wenn Sie tun throw Ex; das Objekt-Slicing findet statt und die neu ausgelöste Ausnahme hat den Typ MyException.

  • das kommt darauf an was Ex ist. Im Beispiel ist es das gleiche Objekt, das per Referenz abgefangen wird (was der Standardweg ist).

    – philsquared

    2. Dezember ’09 um 16:31

  • @Naveen, Objekt-Slicing findet nicht statt, wenn Sie per Referenz gefangen haben. Wenn Sie nach Wert fangen, wäre das Schneiden bereits erfolgt, obwohl zu diesem Zeitpunkt throw; würde Sie retten, weil es die ursprüngliche Ausnahme erneut auslöst)

    – philsquared

    2. Dezember ’09 um 16:35

  • @Phil: nein, lies 15.1/3 und 15.1/6. Selbst wenn ex ist eine Referenz, throw ex; wirft (notwendigerweise) den Referanden nicht, es initialisiert ein temporäres Objekt mit dem Referanden. Das Provisorium kann aufgehoben werden oder nicht. throw;, andererseits wird angegeben, um das vorhandene temporäre wiederzuverwenden.

    – Steve Jessop

    2. Dezember ’09 um 16:42

  • @Phil: Effektiveres C++-Element 12 überprüft, Objekt-Slicing tritt auf. Meine Antwort auf die ursprüngliche Antwort zurückgesetzt.

    – Naveen

    2. Dez. 09 um 16:50

  • @Managu – Werfen / Fangen per Zeiger funktioniert wie erwartet. Der Unterschied besteht darin, dass der Wert eines Zeigers die Adresse ist, aber der Wert einer Referenz das ist, worauf sie verweist (auch wenn sie durch Zeiger unter der Haube implementiert wird).

    – philsquared

    2. Dezember ’09 um 16:51

1641733476 544 Gibt es in C einen Unterschied zwischen „throw und „throw
kurzlebig

[C++ FAQ Lite § 17.9] Was macht throw; (ausnahmslos Objekt nach dem throw Stichwort) bedeuten? Wo würde ich es verwenden?

Möglicherweise sehen Sie Code, der in etwa so aussieht:

class MyException {
public:
  ...
  void addInfo(const std::string& info);
  ...
};

void f()
{
  try {
    ...
  }
  catch (MyException& e) {
    e.addInfo("f() failed");
    throw;
  }
}

In diesem Beispiel ist die Anweisung throw; bedeutet “die aktuelle Ausnahme erneut auslösen.” Hier hat eine Funktion eine Ausnahme abgefangen (durch einen nicht konstanten Verweis), die Ausnahme geändert (indem sie Informationen hinzugefügt hat) und dann die Ausnahme erneut ausgelöst. Dieses Idiom kann verwendet werden, um eine einfache Form von Stack-Trace zu implementieren, indem Sie den wichtigen Funktionen Ihres Programms entsprechende Catch-Klauseln hinzufügen.

Eine andere Redewendung ist der “Exception Dispatcher”:

void handleException()
{
  try {
    throw;
  }
  catch (MyException& e) {
    ...code to handle MyException...
  }
  catch (YourException& e) {
    ...code to handle YourException...
  }
}

void f()
{
  try {
    ...something that might throw...
  }
  catch (...) {
    handleException();
  }
}

Dieses Idiom erlaubt eine einzelne Funktion (handleException()) wiederverwendet werden, um Ausnahmen in einer Reihe anderer Funktionen zu behandeln.

[C++ FAQ Lite § 17.11] Wenn ich dieses Objekt werfe, wie oft wird es kopiert?

Hängt davon ab. Könnte “null” sein.

Objekte, die geworfen werden, müssen einen öffentlich zugänglichen Kopierkonstruktor haben. Der Compiler darf Code generieren, der das geworfene Objekt beliebig oft kopiert, einschließlich null. Aber selbst wenn der Compiler das geworfene Objekt nie tatsächlich kopiert, muss er sicherstellen, dass der Kopierkonstruktor der Ausnahmeklasse vorhanden und zugänglich ist.

(bearbeitet, um mehr Klarheit darüber zu erhalten, was ich für offensichtlich hielt …)

catch(MyException& ex) { throw ex; } darf kopieren ex, mit allen damit verbundenen Problemen; catch(MyException& ex) { throw; } nicht dürfen.

  • Sicher, aber da ich im obigen Code wählen kann, ob ich das eine oder andere tun möchte, was ist der Unterschied?

    – Joshua Fox

    2. Dez. 09 um 16:40

  • Tolle Antwort, ich füge den Kommentar hinzu, dass wir in unserem Code eine Beschleunigung festgestellt haben, indem wir einen großen Block des Ausnahmefangs in seine eigene Funktion verschoben haben. Die Beschleunigung war darauf zurückzuführen, dass die Funktionen verkleinert wurden, indem die Catch-Blöcke in eine Funktion gesteckt wurden.

    – Chollida

    2. Dezember ’09 um 16:41

  • Mir war das Idiom “Ausnahme-Dispatcher” noch nie aufgefallen. Interessant.

    – Greg D

    2. Dez. 09 um 17:18

Wenn Sie eine Ausnahmehierarchie haben, throw ex kann deine Ausnahme schneiden, während throw Gewohnheit. Beispielsweise:

#include <iostream> 
#include <string> 

using namespace std; 

struct base 
{ 
  virtual string who() {return "base";} 
}; 

struct derived : public base 
{ 
  string who() {return "derived";} 
}; 

int main() { 
  try { 
    try { 
      throw derived(); // throws a 'derived'
    }  
    catch (base& ex)  
    { 
      throw ex; // slices 'derived' object to be a 'base' object
    } 
  } 
  catch (base& ex) 
  { 
    cout<<ex.who()<<endl; // prints 'base'
  } 
} 

Veränderung throw ex nur throw, und Sie erhalten eine Ausgabe von derived, was Sie wahrscheinlich erwartet haben.

  • Danke. Das ist überraschend. Ich würde nicht glauben, dass Slicing bei der Behandlung eines Objekts als Referenz auftreten kann.

    – Joshua Fox

    2. Dez. 09 um 16:44

Gibt es in C einen Unterschied zwischen „throw und „throw
philsquared

Du kannst den … benutzen throw; bilden mit catch(...) (das ist die einzige Möglichkeit zum erneuten Werfen, wenn Sie mit catch(…) erwischt wurden).

1641733476 130 Gibt es in C einen Unterschied zwischen „throw und „throw
rmn

Es gibt einen großen Unterschied. Ich habe darüber in meinem Blog geschrieben, unter: https://cpptalk.wordpress.com/2009/08/23/nuances-of-Exception-rethrow/

Schaut gerne mal rein

1641733476 279 Gibt es in C einen Unterschied zwischen „throw und „throw
Priyank Bolia

throw ex wird eine weitere Kopie machen und wird nicht empfohlen throw nur um das aktuelle Ausnahmeobjekt auszulösen.

1641733476 518 Gibt es in C einen Unterschied zwischen „throw und „throw
Josua

throw kann einen nicht standardmäßigen Ausnahmetyp auslösen, der von catch(…) abgefangen wurde (zB strukturierte Ausnahme)

  • Wurde das nicht als “unbeabsichtigter Nebeneffekt in VC6, behoben in VC7” dokumentiert?

    – peterchen

    2. Dezember ’09 um 16:34

  • Ja, das ist ein guter Punkt. In diesem Fall kenne ich jedoch den Ausnahmetyp (MyException). Gibt es also einen Unterschied?

    – Joshua Fox

    2. Dezember ’09 um 16:42

  • @peterchen, ich hoffe nicht. Das war verdammt nützlich, um SEH-Ausnahmen abzufangen, zu bereinigen und erneut auszulösen.

    – Josua

    2. Dezember ’09 um 17:42

.

212120cookie-checkGibt es in C++ einen Unterschied zwischen „throw“ und „throw ex“?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy