初始化枚举的值的行为

时间:2015-01-14 02:42:08

标签: c++ enums initialization language-lawyer value-initialization

首先,我想说,根据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,那么初始化枚举值(如果它可以正常工作)可能会导致未定义的行为?

2 个答案:

答案 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接口!