首先,我想说,根据cppreference.com,对枚举值进行初始化是不可能的。
根据http://en.cppreference.com/w/cpp/language/value_initialization,初始化枚举的值实际上执行零初始化。然后,根据http://en.cppreference.com/w/cpp/language/zero_initialization,零初始化枚举的效果是:
如果
T
是标量类型,则对象的初始值是隐式转换为T
的整数常量零。
但是,整数常数零不能隐式转换为枚举。最终,枚举不能进行价值初始化。这听起来很奇怪,并且枚举值的初始值确实适用于VC,GCC和clang。那么,标准对此有何看法?
其次,根据http://en.cppreference.com/w/cpp/language/static_cast:
整数,浮点或枚举类型可以转换为任何完整的枚举类型(结果是未指定的(直到C ++ 17)未定义的行为(因为C ++ 17)如果表达式的值转换为枚举的基础类型,不是目标枚举值之一)
那么,这是否意味着如果目标枚举的枚举数不等于0
,那么初始化枚举值(如果它可以正常工作)可能会导致未定义的行为?
答案 0 :(得分:3)
评论中给出了答案。我试图解释其背后的整个标准如下。
零初始化
T
类型的对象或引用意味着:
- 如果
获得T
是标量类型(3.9),则将对象初始化为该值 通过将整数文字0
(零)转换为T
;
(枚举是标量类型;§3.9/ 9) 因为转换不是隐含的,我们不是在看§4,而是§5.2.9;
然后,表达式
static_cast<T>(v)
的结果是结果 将表达式v
转换为T
类型。
§5.2.9/ 10定义了如何将整数值转换为枚举类型。
可以将积分或枚举类型的值显式转换为 枚举类型。 如果原始值为,则值不变 在枚举值范围内(7.2)。否则,结果 值未指定(可能不在该范围内)。
必须显示零在所有枚举的枚举值范围内 接下来的五个引用来自§7.2/ 8:
对于其基础类型是固定的枚举,其值为 枚举是基础类型的值。
由于所有允许的基础类型在其值范围*中都包含零,因此会自动提供所需的结果。现在,对于没有固定底层类型的枚举,
否则,对于 e min 最小的枚举 枚举器和 e max 是最大的,值的 枚举是 b min 到 b范围内的值 max ,定义如下:
即。我们必须证明 b min 总是小于或等于零, b max 总是更大或等于零。
让 K 为2的两个 补码表示和0表示一个补码或 符号幅度表示。
b max 是大于或等于 max的最小值(| e min | - K,| e < sub> max |) 并等于 2M - 1 ,其中 M 是一个非负整数。
| e max | 是非负的,两个数字的最大值至少与两个数字一样大。因此 max(| e min | - K,| e max |)也是非负的, b max 必须大于或等于该数字 - 因此我们的第一个要求得到满足。
如果 e min 非负且 - (b < b min 为零sub> max + K)否则。
b min 显然为零或负数: b max 为非负数,如上所示,并且 K 是非负的(0或1),因此它们的和的加法逆是非正的。满足了我们的第二个要求。最后,
如果枚举器列表为空,则为 枚举就像枚举有一个枚举器一样 价值
0
。
通过设置 e min = e max = 0 ,可以得到上述结果。
答案 1 :(得分:2)
1:这可能是不正常的:
enum class SomeEnum : int { V1 = 0, V2 = 1, V3 = 2 };
SomeEnum a = 0; // compile error
SomeEnum b = SomeEnum.V1; // OK
这是对未定义行为的基本保护!
2:是和是:)
SomeEnum c = static_cast<SomeEnum>(1); // = SomeEnum.V2
SomeEnum d = static_cast<SomeEnum>(5); // undefined behavior
根据定义,static_cast是危险的,它只能用于支持serrialization或旧的c接口!