¿Cuál es la mejor manera de inicializar una estructura de campo de bits en C ++?
-
03-07-2019 - |
Pregunta
En C ++, tengo una clase que contiene una estructura de campo de bits anónima. Quiero inicializarlo a cero sin tener que escribir manualmente todos los campos.
Me imagino poniendo la inicialización en tres lugares:
- Crear un constructor en el campo de bits
- Poner a cero en la lista de inicializadores del constructor para la clase que contiene
- Poner a cero en el cuerpo del constructor para la clase que contiene
Este campo de bits tiene muchos campos, y prefiero no enumerarlos todos.
Por ejemplo, vea el siguiente código:
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?
}
¿Es preferible uno de estos? ¿O hay algo más que me estoy perdiendo?
Editar: Basado en la respuesta aceptada a continuación (por Ferruccio) Me decidí por esta solución:
class Big {
// ...
struct bflag_struct {
unsigned int field 1 : 1;
// ...
bflag_struct() { memset(this, 0, sizeof *this); };
}
// ...
}
Solución
Siempre puedes hacer esto en tu constructor:
memset(&bflag, 0, sizeof bflag);
Otros consejos
Unión de la estructura de campo de bits con algo más fácil de inicializar a 0.
Podría usar una unión, aunque eso agregaría un nivel adicional de indirección al acceder a los campos:
class Big {
union {
struct {
unsigned int field1 : 1;
...
} fields;
unsigned int all_fields;
};
...
};
Big::Big()
: all_fields(0),
...
{
...
}
MSVC permite estructuras anónimas dentro de las uniones (consulte, por ejemplo, la definición de D3DMATRIX
en <d3d9.h>
), pero esta es una extensión de C ++ no estándar que debe evitar usar si puede.
Como comentario aparte, a menos que necesite el campo de bits para interactuar con algún código heredado, no debe usarlos. Son inherentemente inportables e ineficientes.
Su uso de un inicializador similar a una función (marcado " ¿Puedo poner a cero bflag aquí? ") es 100% suficiente para inicializar su estructura POD con 0 valores.
A menos que sepa que su compilador está roto a este respecto, hacer cualquier inicialización adicional de esos miembros es inicializarlo dos veces sin ningún beneficio.
EDITAR: Solo por "diversión" Acabo de comprobar esto con VS2005, VS2008, GCC 3.4.4, GCC 4.2 y Borland C ++ 5.5.1 ... solo Borland C ++ 5.5.1 se equivoca.
Y digo 'incorrecto' porque me parece que 8.5 y 8.5.1 del estándar implican que el inicializador de función debería poner a cero la estructura POD.
puede poner a cero la memoria usando ZeroMemory o memset en el constructor de esa manera se ve más limpia.