Каков наилучший способ инициализации структуры битового поля в C ++? - PullRequest
5 голосов
/ 04 марта 2009

В C ++ у меня есть класс, который содержит анонимную структуру битового поля. Я хочу инициализировать его нулем без необходимости вручную записывать все поля.

Я могу представить инициализацию в трех местах:

  1. Создать конструктор в битовом поле
  2. Обнуление в списке инициализатора конструктора для содержащего класса
  3. Обнуление в теле конструктора для содержащего класса

В этом битовом поле много полей, и я бы не стал перечислять их все.

Например, см. Следующий код:

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

Один из них предпочтительнее? Или я что-то пропустил?

Редактировать: На основании принятого ответа ниже (Ферруччо) я остановился на этом решении:

class Big {
    // ...

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

    // ...
}

Ответы [ 6 ]

9 голосов
/ 04 марта 2009

Объединяет структуру битового поля с чем-то более простым для инициализации до 0.

9 голосов
/ 04 марта 2009

Вы всегда можете сделать это в своем конструкторе:

memset(&bflag, 0, sizeof bflag);
6 голосов
/ 04 марта 2009

Вы можете использовать объединение, хотя это добавит дополнительный уровень косвенности при доступе к полям:

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

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

MSVC допускает анонимные структуры внутри объединений (см., Например, определение D3DMATRIX в <d3d9.h>), но это нестандартное расширение C ++, которое следует избегать, если вы можете.

3 голосов
/ 04 марта 2009

Кроме того, если вам не нужно битовое поле для взаимодействия с каким-либо устаревшим кодом, вы не должны их использовать. Они по своей природе непереносимы и неэффективны.

2 голосов
/ 05 марта 2009

Ваше использование подобного функции инициализатора (помеченного «Могу ли я обнулить bflag здесь?») На 100% достаточно для инициализации структуры POD с 0 значениями.

Если вы не знаете, что ваш компилятор не работает в этом отношении, любая дополнительная инициализация этих членов инициализирует его дважды без какой-либо выгоды.

РЕДАКТИРОВАТЬ: Просто для удовольствия, я только что проверил это с VS2005, VS2008, GCC 3.4.4, GCC 4.2 и Borland C ++ 5.5.1 ... только Borland C ++ 5.5.1 ошибается.

И я говорю «неправильно», потому что мне кажется, что 8.5 и 8.5.1 стандарта подразумевают, что подобный функции инициализатор должен обнулять инициализацию структуры POD.

0 голосов
/ 04 марта 2009

Вы можете обнулить память, используя ZeroMemory или memset в конструкторе, чтобы она выглядела чище.

...