Kann Elision in Catch-Anweisungen auftreten?

8

Betrachten Sie eine Ausnahmeklasse mit einem Kopierkonstruktor mit Nebeneffekten.

Kann ein Compiler den Aufruf des Kopierkonstruktors hier überspringen:

%Vor%

Was ist damit?

%Vor%

(Ja, ich weiß, das ist alles sehr hässlich, das wurde von einer anderen Frage inspiriert)

    
R. Martinho Fernandes 13.09.2011, 12:02
quelle

3 Antworten

9

Ja, es kann sowohl beim Werfen als auch beim Fangen entfernt werden. Zum Abfangen kann es nur dann entfernt werden, wenn der in der catch-Klausel angegebene Typ der selbe ist (außer für cv-qualifications) wie der Typ des Ausnahmeobjekts. Für eine formellere und detailliertere Beschreibung siehe C ++ 11 12.8 / 31.

  

... Diese Elision von Kopier- / Verschiebevorgängen, die als Kopier-Elision bezeichnet wird, ist unter den folgenden Umständen zulässig (die kombiniert werden können, um mehrere Kopien zu eliminieren):

     

...

     
  • in einem throw-Ausdruck, wenn der Operand der Name eines nichtflüchtigen automatischen Objekts ist (anders als ein Parameter function oder catch-clause), dessen Geltungsbereich nicht über das Ende des innersten umschließenden try-Blocks hinausreicht (if Es gibt eine), die Operation Kopieren / Verschieben vom Operanden zum Ausnahmeobjekt (15.1) kann weggelassen werden, indem das automatische Objekt direkt in das Ausnahmeobjekt
  • konstruiert wird   

...

     
  • Wenn die Ausnahmedeklaration eines Ausnahmebehandlers (Abschnitt 15) ein Objekt desselben Typs (mit Ausnahme von cv-qualification) als Ausnahmeobjekt (15.1) deklariert, kann die Operation copy / move durch Behandeln der Ausnahme weggelassen werden - Deklaration als Alias ​​für das Exception-Objekt, wenn die Bedeutung des Programms bis auf die Ausführung von Konstruktoren und Destruktoren für das von der Exception-Deklaration deklarierte Objekt unverändert bleibt.
  •   
    
Konstantin Oznobihin 13.09.2011, 12:21
quelle
4

Ich denke, das ist ausdrücklich erlaubt. Für C ++ 03, 15.1 / 3 heißt es:

  

Ein throw-Ausdruck initialisiert ein temporäres Objekt namens   Ausnahmeobjekt,

und 12/15 sagt:

  

wenn ein temporäres Klassenobjekt nicht an eine Referenz gebunden wurde   (12.2) würde in ein Klassenobjekt mit demselben cv-unqualifiziert kopiert werden   type, kann der Kopiervorgang entfallen, indem das Tempo   rary Objekt direkt in das Ziel der ausgelassenen Kopie

Also wird das geheime Versteck, in dem In-Flight-Exceptions gehalten werden, vom Standard als temporär definiert und ist daher für die Kopie-Elision gültig.

Edit: oops, ich habe jetzt weiter gelesen. 15.1 / 5:

  

Wenn die Verwendung des temporären Objekts ohne Änderung aufgehoben werden kann   die Bedeutung des Programms mit Ausnahme der Ausführung von Konstruktoren   und Destruktoren, die mit der Verwendung des temporären Objekts verbunden sind   (12.2), dann kann die Ausnahme im Handler direkt initialisiert werden   mit dem Argument des throw-Ausdrucks.

Wird nicht viel klarer.

Ob dies tatsächlich der Fall ist ... Wenn die catch-Klausel die Exception erneut auslösen würde (auch wenn sie nicht sichtbaren Code aufgerufen hätte, der dies tun könnte), dann benötigt die Implementierung das "temporäre Objekt, das das Exception-Objekt aufgerufen hat" zusammen zu sein. Es kann also Einschränkungen geben, wenn diese Kopie möglich ist. Natürlich kann eine leere Fangklausel sie nicht erneut auslösen.

    
Steve Jessop 13.09.2011 12:22
quelle
0

Ja. Wenn die catch die Ausnahme durch Referenz abfängt, dann wird es keine Kopie geben (nun, das ist per Definition).

Aber ich denke, das ist nicht Ihre Frage, und ich glaube, der Code, den Sie geschrieben haben, ist absichtlich geschrieben, ohne Referenz zu erwähnen. Wenn das der Fall ist, dann ja, auch in diesem Fall kann die Kopie gelöscht werden. Tatsächlich ist die Initialisierung der Variable in catch theoretisch direkte Initialisierung . Und eine Kopie in einer Direkt-Initialisierung kann vom Compiler weggelassen werden, wo es möglich ist.

C ++ 03 §8.5 / 14 gelesen,

  

[...] In bestimmten Fällen ist es einer Implementierung gestattet, das Kopieren zu eliminieren, das dieser direkten Initialisierung innewohnt, indem das Zwischenergebnis direkt in das zu initialisierende Objekt konstruiert wird;

    
Nawaz 13.09.2011 12:11
quelle