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.
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.
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).