Каков наилучший способ инициализации структуры битового поля в C ++?
-
03-07-2019 - |
Вопрос
В C ++ у меня есть класс, который содержит анонимную структуру битовых полей. Я хочу инициализировать его нулем без необходимости выписывать все поля вручную.
Я могу представить инициализацию в трех местах:
<Ол>В этом битовом поле много полей, и я бы не стал перечислять их все.
Например, см. следующий код:
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); };
}
// ...
}
Решение
Вы всегда можете сделать это в своем конструкторе:
memset(&bflag, 0, sizeof bflag);
Другие советы
Объедините структуру битового поля с чем-то более простым для инициализации в 0.
Вы могли бы использовать объединение, хотя это добавило бы дополнительный уровень косвенности при доступе к полям:
class Big {
union {
struct {
unsigned int field1 : 1;
...
} fields;
unsigned int all_fields;
};
...
};
Big::Big()
: all_fields(0),
...
{
...
}
MSVC допускает анонимные структуры внутри союзов (см., например, определение D3DMATRIX
в <d3d9.h>
), но это нестандартное расширение C ++, которое следует избегать, если вы можете.
Кроме того, если вам не нужно битовое поле для взаимодействия с каким-либо устаревшим кодом, вы не должны их использовать. Они по своей природе непереносимы и неэффективны. Р>
Использование функционально-подобного инициализатора (помеченного " можно ли здесь обнулить 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.
вы можете обнулить память, используя ZeroMemory или memset в конструкторе, чтобы она выглядела чище.