55 votes

Initialisation d'une union avec un constructeur non trivial

J'ai une structure qui j'ai créer un constructeur pour initialiser les membres à 0. J'ai vu dans les anciens compilateurs que lorsqu'en mode release, sans en faire un memset à 0, les valeurs ne sont pas initialisés.

Je veux maintenant utiliser cette structure dans une union, mais des erreurs parce que c'est un non-trivial constructeur.

Donc, la question 1. Le compilateur par défaut mis en œuvre constructeur de garantir que tous les membres d'une structure sera initialisé à null? Le non-trivial constructeur a tout simplement un memset de tous les membres de '0' pour assurer la propreté de la structure.

Question 2: Si un constructeur doit être spécifié sur la base de la structure, comment un syndicat soit mis en œuvre pour contenir un élément et d'assurer un 0 initialisé élément de base?

47voto

Question 1: par Défaut, les constructeurs ne initialiser POD membres à 0 selon la norme C++. Voir le texte cité ci-dessous.

Question 2: Si un constructeur doit être spécifié dans une classe de base, alors que la classe ne peut pas faire partie d'un syndicat.

Enfin, vous pouvez fournir un constructeur pour votre union:

union U 
{
   A a;
   B b;

   U() { memset( this, 0, sizeof( U ) ); }
};

Pour Q1:

À partir de C++03, 12.1 Constructeurs, page 190

La implicitement par défaut définis par le constructeur effectue l'ensemble des initialisations de l' classe qui serait effectuée par un utilisateur écrit dans le constructeur par défaut pour la classe avec un vide mem-initialiseur de liste (12.6.2) et un vide corps de la fonction.

À partir de C++03, 8.5 Initialiseurs, page 145

À défaut d'initialisation d'un objet de type T signifie:

  • si T est un non-POD type de classe (article 9), le constructeur par défaut pour T est appelé (et le l'initialisation est mal formé, si T n'a pas accessible par défaut le constructeur);
  • si T est de type tableau, chaque élément par défaut est initialisée;
  • sinon, l'objet est initialisé à zéro.

À zéro-initialiser un objet de type T signifie:

  • si T est un type scalaire (3.9), l'objet est défini à la valeur de 0 (zéro) est converti en T;
  • si T est un non-union type de classe, chaque membre de données statiques et chaque classe de base sous-objet est initialisé à zéro;
  • si T est un type d'union, l'objet premier de données nommée membre est initialisé à zéro;
  • si T est de type tableau, chaque élément est initialisé à zéro;
  • si T est un type de référence, pas d'initialisation est effectuée.

Pour Le T2:

À partir de C++03, 12.1 Constructeurs, page 190

Un constructeur est trivial si il est implicitement déclarée de constructeur par défaut, et si:

  • sa classe n'a pas de fonctions virtuelles (10.3) et pas de virtuel classes de base (10.1), et
  • tous les directe les classes de base de sa classe ont trivial constructeurs, et
  • pour tous les non statiques de données des membres de sa classe qui sont de type classe (ou d'une matrice, de celui-ci), chaque classe a un trivial constructeur

À partir de C++03, 9.5 Syndicats, page 162

Une union peut avoir les fonctions membres (y compris les constructeurs et destructeurs), mais pas virtuel (10.3) de fonctions. Un syndicat ne peut pas les classes de base. Un syndicat ne peut pas être utilisée comme classe de base.Un objet d'une classe avec un non-trivial constructeur (12.1), un non-trivial constructeur de copie (12.8), un non-trivial destructeur (12.4), ou à un non-trivial copie opérateur d'affectation (13.5.3, 12.8) ne peut pas être membre d'un syndicat, ni un tableau de ces objets

2voto

Adam Rosenfield Points 176408

Comme mentionné dans le commentaire de Greg Rogers au message de Unsesen , vous pouvez donner à votre syndicat un constructeur (et un destructeur si vous le souhaitez):

 struct foo
{
    int a;
    int b;
};

union bar
{
    bar() { memset(this, 0, sizeof(*this)); }

    int a;
    foo f;
};
 

0voto

John Dibling Points 56814

Pouvez-vous faire quelque chose comme ça?

 class Outer
{
public:
    Outer()
    {
    	memset(&inner_, 0, sizeof(inner_));
    }
private:
    union Inner
    {
    	int qty_;
    	double price_;
    } inner_;
};
 

... ou peut-être quelque chose comme ça?

 union MyUnion
{
    int qty_;
    double price_;
};

void someFunction()
{
    MyUnion u = {0};
}
 

-1voto

Michel Points 992

Vous devrez attendre que C ++ 0x soit pris en charge par les compilateurs pour l'obtenir. Jusque-là, désolé.

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