47 votes

La norme C ++ garantit-elle que l'initialisation uniforme est sans exception?

#include <iostream>

using namespace std;

struct A
{
    A() { cout << "A" << endl; }
    ~A() { cout << "~A" << endl; }
};

A Ok() { return {}; }
A NotOk() { throw "NotOk"; }

struct B
{
    A a1;
    A a2;
};

void f(B) {}

int main()
{
    try
    {
        f({ Ok(), NotOk() });
    }
    catch (...)
    {}
}

vc++ et clang sortie:

A
~A

Alors qu' gcc sorties:

A

Il semble un sérieux bug de GCC.

Pour référence, voir GCC bug 66139 et "Un sérieux bug de GCC" par Andrzej Krzemieński.

Je me demande simplement:

Le standard C++ garantir que l'initialisation uniforme est exception-safe?

31voto

AndyG Points 3298

Il semble donc:

Curieusement au §6.6/2 Sauter Consolidés (stmt.sauter] de tous les lieux (N4618):

Lors de la sortie du champ d'application (cependant accompli), les objets avec automatique durée de stockage (3.7.3) qui ont été construits dans cette étendue détruit dans l'ordre inverse de leur construction. [ Note: Pour temporaires, voir 12.2. -fin de la remarque ] le Transfert de sortir d'une boucle, d'un bloquer, ou de nouveau passé une variable initialisée avec stockage automatique durée implique la destruction d'objets avec stockage automatique durée qui sont dans la portée au point transférés à partir, mais pas à le point de transféré à. (Voir 6.7 pour les transferts en blocs). [ Note: Toutefois, le programme peut être résilié (en appelant std::exit()ou std::abort() (18.5), par exemple), sans détruire les objets de la classe automatique de la durée de stockage. -la note de fin ]

Je pense que l'accent est mis ici sur l' "(cependant accompli)". Cela inclut une exception (mais exclut les choses qui causent une std::terminate).


MODIFIER

Je pense qu'une meilleure référence est §15.2/3 Constructeurs et destructeurs [à l'exception des.ctor] (l'accent de la mienne):

Si l' initialisation ou de la destruction d'un objet autre que par déléguer constructeur est résilié par l'une exception, le destructeur est appelé pour chaque objet direct de sous-objets et, pour un d'objet, de classe de base virtuelle sous-objets, dont l'initialisation (8.6) et dont le destructeur n'a pas encore commencé l'exécution, sauf que dans le cas de la destruction, de la variante de membres d'un l'union-comme la classe, ne sont pas détruits. Les sous-objets sont détruits dans l'ordre inverse de l'achèvement des travaux de construction. Ces la destruction est séquencée avant d'entrer dans un gestionnaire de l' fonction-essayez-le bloc du constructeur ou le destructeur, le cas échéant.

Cela permettrait de comprendre globale de l'initialisation (dont j'ai appris aujourd'hui peut être appelé non-vides de sens, d'initialisation)

...et pour les objets avec les constructeurs, nous pouvons citer §12.6.2/12 [classe.de la base.init](l'accent de la mienne):

Dans un non-la délégation de constructeur, destructeur pour chaque potentiellement construite sous-objet de type classe est potentiellement invoquée (12.4). [ Remarque: Cette disposition garantit que les destructeurs peuvent être appelés pour entièrement construit des sous-objets dans le cas où une exception est levée(15.2). -la note de fin ]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X