Question

En C ++, j'ai une classe qui contient une structure de champ de bits anonyme. Je veux l'initialiser à zéro sans avoir à écrire manuellement tous les champs.

Je peux imaginer de placer l'initialisation à trois endroits:

  1. Créer un constructeur dans le champ de bits
  2. Zéro dans la liste des initialiseurs du constructeur pour la classe contenante
  3. Zéro dans le corps du constructeur pour la classe contenante

Ce champ de bits comporte de nombreux champs et je préférerais ne pas les énumérer tous.

Par exemple, voyez le code suivant:

class Big {
    public:
        Big();

        // Bitfield struct
        struct bflag_struct {
            unsigned int field1 : 1;
            unsigned int field2 : 2;
            unsigned int field3 : 1;
            // ...
            unsigned int field20 : 1;
            // bflag_struct(); <--- Here?
        } bflag;

        unsigned int integer_member;
        Big         *pointer_member;
}

Big::Big()
  : bflag(),             // <--- Can I zero bflag here?
    integer_member(0),
    pointer_member(NULL)
{
    // Or here?
}

Est-ce que l'un de ceux-ci est préférable? Ou y a-t-il autre chose qui me manque?

Edit: Sur la base de la réponse acceptée ci-dessous (par Ferruccio), j’ai opté pour cette solution:

class Big {
    // ...

    struct bflag_struct {
        unsigned int field 1 : 1;
        // ...
        bflag_struct() { memset(this, 0, sizeof *this); };
    }

    // ...
}
Était-ce utile?

La solution

Vous pouvez toujours le faire dans votre constructeur:

memset(&bflag, 0, sizeof bflag);

Autres conseils

Unionnez la structure de champ de bits avec quelque chose de plus facile à initialiser à 0.

Vous pouvez utiliser une union, bien que cela ajoute un niveau supplémentaire d'indirection lors de l'accès aux champs:

class Big {
    union {
        struct {
            unsigned int field1 : 1;
            ...
        } fields;
        unsigned int all_fields;
    };
    ...
};

Big::Big()
  : all_fields(0),
    ...
{
    ...
}

MSVC autorise les structures anonymes à l'intérieur des unions (voir, par exemple, la définition de D3DMATRIX dans <d3d9.h>), mais il s'agit d'une extension C ++ non standard que vous devriez éviter d'utiliser si vous le pouvez.

En passant, vous ne devriez pas les utiliser, sauf si vous avez besoin du champ de bits pour vous connecter à un code hérité. Ils sont intrinsèquement inutilisables et inefficaces.

Votre utilisation d'un initialiseur semblable à une fonction (marqué & "; puis-je mettre le bflag à zéro ici? &";) est suffisante à 100% pour initialiser votre structure POD avec des valeurs 0.

À moins que vous ne sachiez que votre compilateur est endommagé à cet égard, l'initialisation supplémentaire de ces membres l'initialise deux fois sans aucun avantage.

EDIT: Juste pour "plaisir", je viens de vérifier cela avec VS2005, VS2008, GCC 3.4.4, GCC 4.2 et Borland C ++ 5.5.1 ... seul Borland C ++ 5.5.1 se trompe.

Et je dis 'faux' car il me semble que 8.5 et 8.5.1 de la norme impliquent que l'initialiseur de type fonction devrait initialiser à zéro la structure POD.

vous pouvez mettre à zéro la mémoire en utilisant ZeroMemory ou memset dans le constructeur afin que l'apparence soit plus nette.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top