Qual é a melhor maneira de inicializar um struct bitfield em C ++?
-
03-07-2019 - |
Pergunta
Em C ++, eu tenho uma classe que contém um struct bitfield anônimo. Eu quero inicializar a zero sem ter que escrever manualmente todos os campos.
Eu posso imaginar colocando a inicialização em três locais:
- Crie um construtor na bitfield
- Zero na lista inicializador do construtor para a classe contendo
- zero para fora no corpo do construtor da classe contendo
Esta bitfield tem muitos campos, e eu prefiro não enumerá-los todos.
Por exemplo, veja o seguinte 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?
}
é um desses preferível? Ou há algo mais que eu estou perdendo?
Edit: Com base na resposta aceite abaixo (por Ferruccio) Eu estabeleci-me sobre esta solução:
class Big {
// ...
struct bflag_struct {
unsigned int field 1 : 1;
// ...
bflag_struct() { memset(this, 0, sizeof *this); };
}
// ...
}
Solução
Você pode sempre fazer isso em seu construtor:
memset(&bflag, 0, sizeof bflag);
Outras dicas
União a estrutura bitfield com algo mais fácil para inicializar a 0.
Você pode usar uma união, apesar de que gostaria de acrescentar um nível extra de indireção quando acessar os campos:
class Big {
union {
struct {
unsigned int field1 : 1;
...
} fields;
unsigned int all_fields;
};
...
};
Big::Big()
: all_fields(0),
...
{
...
}
MSVC permite estruturas anônimos dentro de sindicatos (ver, por exemplo, a definição de D3DMATRIX
em <d3d9.h>
), mas esta é uma extensão não-padrão C ++ que você deve evitar usar se você puder.
Como um aparte, a menos que você precisa do bitfield a interface para algum código legado, você não deve usá-los. Eles são inerentemente são portável e ineficiente.
O uso de um ( "Can I bflag de zero aqui?" Marcado) initializer like-função é 100% suficiente para inicializar sua estrutura POD com 0 valores.
Se você não sabe o seu compilador está quebrado, a este respeito, fazendo qualquer inicialização adicional dos membros está inicializando-lo duas vezes para nenhum benefício.
EDIT:. Apenas para 'diversão' Acabei de verificar isso com VS2005, VS2008, GCC 3.4.4, GCC 4.2, e Borland C ++ 5.5.1 ... só que Borland C ++ 5.5.1 erra
E eu digo 'errado', porque parece-me que 8.5 e 8.5.1 da norma implica que a função-like initializer deve zerar-init a estrutura POD.
você poderia Zero a memória usando ZeroMemory ou memset no construtor dessa forma que pareça de mais limpo.