C++11 枚举类枚举的实际值是否保持不变?

C++11 枚举类枚举的实际值是否保持不变?,c++11,enums,C++11,Enums,为不完整的服务器(如: enum class Command : uint32_t { LOGIN, MESSAGE, JOIN_CHANNEL, PART_CHANNEL, INVALID }; 我是否可以期望将Command::LOGIN转换为整数将始终给出相同的值 跨编译器 跨编译器版本 如果我添加另一个枚举 如果我删除枚举 转换Command::LOGIN如下所示: uint32_t number = static_cast<uint3

为不完整的服务器(如:

enum class Command : uint32_t {
    LOGIN,
    MESSAGE,
    JOIN_CHANNEL,
    PART_CHANNEL,
    INVALID
};
我是否可以期望将
Command::LOGIN
转换为整数将始终给出相同的值

  • 跨编译器
  • 跨编译器版本
  • 如果我添加另一个枚举
  • 如果我删除枚举
转换
Command::LOGIN
如下所示:

uint32_t number = static_cast<uint32_t>(Command::LOGIN);
uint32\u t number=static\u cast(命令::登录);
关于我在这里做什么的一些额外信息。通过将枚举转换为整数并将其发送到服务器/客户机,可以将该枚举馈送到线路上。我真的不特别关心数字是多少,只要它始终保持不变。如果它不会保持不变,那么显然我将不得不通过通常的方式提供我自己的数字

现在我暗自怀疑,它会根据编译代码时使用的编译器而改变,但我想确定一下

附加问题:编译器/语言如何确定要用于
命令::登录的数字


在提交这个问题之前,我注意到从3137527848到0的一些变化,所以依赖它不改变显然是无效的。我仍然很好奇这个数字是如何确定的,以及这个数字是如何或为什么变化的。

Command::LOGIN将始终为0,只要它是列表中的第一个枚举。只需小心其余的枚举,因为它们将根据计算机使用的是big-endian还是little-endian而具有不同的二进制表示形式。

Command::LOGIN始终为0,只要它是列表中的第一个枚举。只需小心其余的枚举,因为它们具有不同的二进制表示形式,具体取决于计算机使用的是big-endian还是little-endian。

如果将显式整数值指定给枚举常量,则保证在转换为整数类型时始终具有相同的值

只需执行以下操作:

enum class Command : uint32_t {
    LOGIN = 12,
    MESSAGE = 46,
    JOIN_CHANNEL = 5,
    PART_CHANNEL = 0,
    INVALID = 42
};
如果不显式指定任何值,则会隐式设置这些值,从零开始,并随着列表的下移而增加一

从草案n3485中引用:

[dcl.enum]第2段

使用仅为enum的enum键声明的枚举类型是 非范围枚举,其枚举数是非范围枚举数。 枚举键enum class和enum struct在语义上是等价的; 使用其中之一声明的枚举类型是作用域 枚举,其枚举数是作用域枚举数。[…] 枚举器列表中的标识符声明为常量,可以 出现在需要常量的地方。带有 =为关联的枚举数提供由常量表达式指示的值。如果第一个枚举数没有初始值设定项,则 相应常数的值为零An 没有初始值设定项的枚举数定义为枚举数提供 通过将前一个枚举数的值增加 一个


依赖于此的缺点是,如果列表顺序在将来以某种方式发生更改,那么代码可能会自动中断,因此我建议您使用显式。

如果将显式整数值指定给枚举常量,则可以保证在转换为整数类型时始终具有相同的值

只需执行以下操作:

enum class Command : uint32_t {
    LOGIN = 12,
    MESSAGE = 46,
    JOIN_CHANNEL = 5,
    PART_CHANNEL = 0,
    INVALID = 42
};
如果不显式指定任何值,则会隐式设置这些值,从零开始,并随着列表的下移而增加一

从草案n3485中引用:

[dcl.enum]第2段

使用仅为enum的enum键声明的枚举类型是 非范围枚举,其枚举数是非范围枚举数。 枚举键enum class和enum struct在语义上是等价的; 使用其中之一声明的枚举类型是作用域 枚举,其枚举数是作用域枚举数。[…] 枚举器列表中的标识符声明为常量,可以 出现在需要常量的地方。带有 =为关联的枚举数提供由常量表达式指示的值。如果第一个枚举数没有初始值设定项,则 相应常数的值为零An 没有初始值设定项的枚举数定义为枚举数提供 通过将前一个枚举数的值增加 一个

依赖于此的缺点是,如果列表顺序在将来发生某种变化,那么代码可能会自动中断,因此我建议您明确表示。

来自C++11标准(或者更确切地说,n3485):

[dcl.enum]/2

如果第一个枚举数没有初始值设定项,则相应常量的值为零。没有初始值设定项的枚举数定义为枚举数提供通过将前一个枚举数的值增加1而获得的值

另外,[expr.static.cast]/9

作用域枚举类型的值可以显式转换为整型。如果原始值可以由指定的类型表示,则该值将保持不变

我认为很明显,枚举数的值可以用
uint32\u t
表示;如果不是,则[dcl.enum]/5会说“如果枚举数的初始化值不能由基础类型表示,则程序的格式不正确。”

因此,只要您使用基础类型进行转换(显式地或通过
std::subground_type::type
),这些枚举数的值都是固定的,只要您不在它们前面添加任何枚举数(在同一枚举中),也不改变它们的顺序

作为尼古拉斯·路易斯·吉勒莫,请注意可能的d