Qual è il modo migliore per inizializzare una struttura bitfield in C ++?
-
03-07-2019 - |
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:
- Crea un costruttore nel campo bit
- Azzerare l'elenco di inizializzatori del costruttore per la classe contenente
- 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); };
}
// ...
}
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.