C ++ wirft Klassenmitglieder

8

Ich habe den folgenden C ++ Code

%Vor%

Frage: Ist dieser Code gültig? Ich könnte argumentieren, dass das Zurückgeben eines Verweises auf das Klassenmitglied fast immer nicht gültig ist (und ich bin sicher, dass alle dieser Aussage zustimmen). Mein Kollege behauptet jedoch, dies sei bei throw nicht der Fall.

P.S. nach dem Ändern von catch (const E& e) in catch (E e) scheint ein böser Fehler verschwunden zu sein, der meine Position stärkt - dass dieser Code nicht gültig ist.

    
Solenodon Paradoxus 20.10.2015, 16:30
quelle

3 Antworten

7
  

Meine Behauptung ist, dass e durch Referenz nicht zu erfassen ist, da e ein Mitglied von w ist und w im Fangbereich nicht lebt.

Ihre Behauptung ist falsch. throw e; gibt eine Kopie des Members aus, und diese Kopie ist im Bereich der Catch gültig.

§ 15.1 / 3 (n3797 Entwurf):

  

Ausnahmekopie auslösen - initialisiert (   8.5   ,    12.8   ) ein temporäres Objekt, genannt   Ausnahmeobjekt   . Das   temporary ist ein Lvalue und wird verwendet, um die im Matching angegebene Variable zu initialisieren   Handler   (   15.3   ). Wenn die   Der Typ des Ausnahmeobjekts wäre ein unvollständiger Typ oder ein Zeiger auf einen anderen unvollständigen Typ   (möglicherweise cv-qualifiziert)   Leere   das Programm ist schlecht geformt. Bewertung a   Wurf-Ausdruck   mit einem Operanden wirft   eine Ausnahme; Der Typ des Ausnahmeobjekts wird bestimmt, indem eine beliebige oberste Ebene entfernt wird   Lebenslauf-Qualifikanten   von dem   statischer Typ des Operanden und Anpassung des Typs von "Array of   T   "Oder" Funktion kehrt zurück   T   "Nach" Zeiger auf   T   "Oder" Zeiger auf Funktion kehrt zurück   T   , "Jeweils.

Catching by const referenz ist die bevorzugte Methode, um Ausnahmen abzufangen. Es erlaubt Abfangen von Derivaten von std::exception ohne das Exception-Objekt zu schneiden.

    
user2079303 20.10.2015, 16:54
quelle
2

Ich denke, der relevante Punkt ist:

  

15.1. Ausnahme auslösen:

     

p3. Ein throw-Ausdruck initialisiert ein temporäres Objekt , das so genannte Exception-Objekt, dessen Typ bestimmt wird   Entfernen Sie alle cv-Qualifikationsmerkmale auf oberster Ebene vom statischen Typ des Operanden throw und passen Sie den Typ an   von "Array von T" oder "Funktion, die T zurückgibt" zu "Zeiger zu T" bzw. "Zeiger zu Funktion, die T zurückgibt".    Das temporäre ist ein Lvalue und wird verwendet, um die Variable zu initialisieren, die in dem passenden Handler (15.3) genannt wird. If   Der Typ des Ausnahmeobjekts wäre ein unvollständiger Typ oder ein Zeiger auf einen anderen unvollständigen Typ   als (möglicherweise cv-qualifiziert) void das Programm ist schlecht gebildet. Außer für diese Einschränkungen und die Einschränkungen   Bei der in 15.3 erwähnten Typübereinstimmung wird der Operand von throw genau wie ein Funktionsargument in a behandelt   call (5.2.2) oder der Operand einer return-Anweisung.

Dies ist aus dem Entwurf für C ++ 11 Betonung meiner.

Es bedeutet im Grunde, dass ein temporäres Objekt aus dem Argument throw erstellt wurde. Genauso wie es eine Funktion E f(){return private_e;} gab und diese als Argument für den entsprechenden Handler verwendet wurde. Sie hätten also zwei mögliche Kopien, wenn Sie sich nicht durch Bezugnahme fangen.

Wahrscheinlich auch relevant:

  

p5. Wenn das geworfene Objekt ein Klassenobjekt ist, sollten der copy / move-Konstruktor und der Destruktor zugänglich sein.   auch wenn der Kopier- / Verschiebevorgang deaktiviert ist (12.8).

    
luk32 20.10.2015 17:08
quelle
-4

Wenn der Konstruktor fehlschlägt / wirft, existiert w nicht. Also "w.throwException ()" ist nicht gültig.

    
kjpus 20.10.2015 16:39
quelle

Tags und Links