struct bitfield {
int i = 0; // ok
int j : 8 = 0; // error: lvalue required as left operand of assignment
};
使用c++ 11"类内初始化"功能初始化位字段的正确语法是什么?
这被作为c++标准的核心问题1341提出,但在2015年10月被c++核心工作组拒绝为NAD ("not a defect") -参见http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1341
使用c++ 11"类内初始化"功能初始化位字段的正确语法是什么?
不能在类中初始化位域。c++ 11标准第9.2段规定了类成员声明符的语法:
如你所见,位域成员的声明符不能以大括号或等号初始化式结束。[…]
member-declarator:
声明符virt-specifier-seq(opt) pure-specifier(opt)
说明符brace-or-equal-initializer(选择)
identifier(opt) attribute-specifier-seq(opt): constant-expression
你可以写一个带初始化列表的构造函数,为你的位域提供默认值。
struct bitfield {
int i;
int j : 8;
bitfield() : i(0), j(0) {};
};
您也可以使用默认值创建只读字段。
struct _UserRegister1
{
uint8_t _RES0 : 1;
const uint8_t reserved1 : 1;
uint8_t _HTRE : 1;
const uint8_t reserved2 : 3;
uint8_t _VDDS : 1;
uint8_t _RES1 : 1;
_UserRegister1() : reserved1(1), reserved2(7) {};
};
c++ 11没有提供任何默认初始化位域的语法,但c++ 20提供了。
这意味着当你的c++编译器支持c++ 20时,你的例子编译得很好:
struct bitfield {
int i = 0; // ok
int j : 8 = 0; // ok since C++20
int k : 8 {0}; // ditto
};
请注意,您可能需要显式启用对c++ 20的支持,例如在使用不太新的GCC/Clang版本时使用-std=c++20
。
不能(在c++ 11中)在类中初始化位域。
在MSVC和gcc(带扩展)中,匿名的union
和struct
代码可以让您绕过这一点。
struct bitfield {
int i = 0; // ok
union {
uint32_t raw = 0;
struct {
int j : 8;
int x : 3;
};
};
};
在中,我们将固定大小的raw
与union
混合在位域中,然后在类中初始化raw
元素。