Domanda

In C ++, ho una classe che contiene una struttura bitfield anonima. Voglio inizializzarlo a zero senza dover scrivere manualmente tutti i campi.

Posso immaginare di mettere l'inizializzazione in tre punti:

  1. Crea un costruttore nel campo bit
  2. Azzerare l'elenco di inizializzatori del costruttore per la classe contenente
  3. Azzera nel corpo del costruttore per la classe contenitore

Questo bitfield ha molti campi e preferirei non elencarli tutti.

Ad esempio vedere il seguente codice:

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?
}

È preferibile uno di questi? O c'è qualcos'altro che mi manca?

Modifica: in base alla risposta accettata di seguito (di Ferruccio) ho optato per questa soluzione:

class Big {
    // ...

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

    // ...
}
È stato utile?

Soluzione

Puoi sempre farlo nel tuo costruttore:

memset(&bflag, 0, sizeof bflag);

Altri suggerimenti

Unisci la struttura dei bitfield con qualcosa di più facile da inizializzare a 0.

Potresti usare un sindacato, anche se ciò aggiungerebbe un ulteriore livello di riferimento indiretto quando accedi ai campi:

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

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

MSVC consente strutture anonime all'interno dei sindacati (vedi, ad esempio, la definizione di D3DMATRIX in <d3d9.h>), ma questa è un'estensione C ++ non standard che dovresti evitare di usare se puoi.

A parte questo, a meno che tu non abbia bisogno del bitfield per interfacciarsi con un codice legacy, non dovresti usarli. Sono intrinsecamente non portabili e inefficienti.

L'uso di un inizializzatore simile a una funzione (contrassegnato con " Posso azzerare bflag qui? ") è sufficiente al 100% per inizializzare la struttura POD con 0 valori.

A meno che tu non sappia che il tuo compilatore è rotto a questo proposito, fare qualsiasi ulteriore inizializzazione di quei membri lo sta inizializzando due volte senza alcun vantaggio.

EDIT: Solo per "divertimento" ho appena verificato questo con VS2005, VS2008, GCC 3.4.4, GCC 4.2 e Borland C ++ 5.5.1 ... solo Borland C ++ 5.5.1 sbaglia.

E dico 'sbagliato' perché mi sembra che 8.5 e 8.5.1 dello standard implicino che l'inizializzatore simile a una funzione dovrebbe zero-init la struttura POD.

potresti azzerare la memoria usando ZeroMemory o memset nel costruttore in modo che appaiano più puliti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top