在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?
}
其中一个更好吗?或者还有其他我想念的东西?
编辑:根据下面接受的答案(Ferruccio),我决定采用这个解决方案:
class Big {
// ...
struct bflag_struct {
unsigned int field 1 : 1;
// ...
bflag_struct() { memset(this, 0, sizeof *this); };
}
// ...
}
答案 0 :(得分:9)
您总是可以在构造函数中执行此操作:
memset(&bflag, 0, sizeof bflag);
答案 1 :(得分:9)
将bitfield结构与更容易初始化为0的内容结合起来。
答案 2 :(得分:6)
您可以使用联合,虽然这会在访问字段时添加额外的间接级别:
class Big {
union {
struct {
unsigned int field1 : 1;
...
} fields;
unsigned int all_fields;
};
...
};
Big::Big()
: all_fields(0),
...
{
...
}
MSVC允许联合内部的匿名结构(参见D3DMATRIX
中的<d3d9.h>
的定义),但这是一个非标准的C ++扩展,如果可以,你应该避免使用它。
答案 3 :(得分:3)
顺便说一句,除非您需要将bitfield连接到某些遗留代码,否则不应使用它们。它们本质上是不可移植且效率低下的。
答案 4 :(得分:2)
你使用类似函数的初始值设定项(标记为“我可以将bflag归零吗?”)100%足以用0值初始化POD结构。
除非你知道你的编译器在这方面有所破坏,否则对这些成员进行任何额外的初始化都会将它初始化两次而没有任何好处。
编辑:只是为了'有趣'我刚用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结构进行零启动。
答案 5 :(得分:0)
你可以在构造函数中使用ZeroMemory或memset将内存归零,使其看起来更清晰。
答案 6 :(得分:0)
BTW C ++ 20支持初始化类定义中的位字段,例如
class ... {
int foo : 1 {};
}
带有-std = c ++ 2a的gcc启用