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:

  1. Crie um construtor na bitfield
  2. Zero na lista inicializador do construtor para a classe contendo
  3. 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); };
    }

    // ...
}
Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top