枚举类型变量的默认值是什么?

72

这个问题很简单:

#include <iostream>

enum SomeEnum {  
    EValue1 = 1,  
    EValue2 = 4
};

int main() {
    SomeEnum enummy;
    std::cout << (int)enummy;
}

输出会是什么?

注意:这不是一次面试,这段代码是我从之前的开发者那里继承来的。这里使用的流操作符只是举例,实际继承的代码并没有它。


1
不,我只是在看这个继承的代码库,有这种代码,很遗憾... - Haspemulator
从答案中可以看出,这只是另一个好老的规则的确认:“永远不要编写原型”。但这就是大多数开发人员必须处理的 - 别人的原型... - Haspemulator
22
当我写下“问题很简单”时,我的意思是这个“问题”很简单,也就是说很容易提出,当然,并不是说答案很简单。 - Haspemulator
@David Hammen:它在互联网某个地方,我不记得来源了。但是背后的原理是:每个原型都倾向于成为生产软件,但通常它们并不是最优质的。因此,“永远不要编写原型”在这里意味着“始终像生产代码一样编写代码”。 对于我的特定问题,原型是我从之前的开发人员那里收到的代码(你知道的,像“拿这个原型并从中制作生产代码”),其中包括未初始化的枚举变量之类的东西。 - Haspemulator
1
@QuentinUK:你会得到一个“任意”的数字;“随机”意味着非常具体的东西。但事实上,我相信这种行为是未定义的。 - Keith Thompson
显示剩余4条评论
1个回答

71

该程序存在未定义行为。枚举变量enummy的值是不确定的。从概念上讲,您的代码和以下代码之间没有区别:

int main() {
   int i;          //indeterminate value
   std::cout << i; //undefined behavior
};

如果您在命名空间范围内定义了变量,它将被初始化为0。
enum SomeEnum {  
    EValue1 = 1,  
    EValue2 = 4,  
};
SomeEnum e; // e is 0
int i;      // i is 0

int main()
{
    cout << e << " " << i; //prints 0 0 
}

不要惊讶,e 可以具有与任何 SomeEnum 枚举值不同的值。每个枚举类型都有一个底层整数类型(如 intshortlong),该枚举类型对象的可能值集是底层整数类型具有的值集。枚举只是一种方便地命名一些值并创建新类型的方式,但您不会将枚举的值限制为枚举器值的集合。 更新: 一些支持我的引用:

对类型 T 的对象进行零初始化意味着:
— 如果 T 是标量类型(3.9),则将对象设置为转换为 T 的值为 0(零)的值;

请注意,枚举是标量类型。

对类型 T 的对象进行值初始化意味着:
— 如果 T 是类类型 blah blah
— 如果 T 是非联合类 类型 blah blah
— 如果 T 是数组类型,则 blah blah — 否则,对象将被零初始化

因此,我们进入了“否则”部分。命名空间范围的对象将被值初始化。


2
@Haspemulator:Armen的解释隐含或明确地涵盖了许多内容:从未初始化的变量中读取、静态变量的初始化、枚举类型到整数值的隐式标准转换等。在我看来,期望他为所有这些问题识别出标准的相关部分是不合理的,你需要花些时间阅读C++基础知识。 - Tony Delroy
@Tony:是的,我明白。当时Armen的回答只有一句话,所以我写了这个评论。 :) - Haspemulator
@Haspemulator:哦,不,这并不意味着所有UB的情况都被明确提到。有一个特殊条款规定,所有未被明确定义的行为都是隐式未定义的!我的原始回答还要再长一句 :) - Armen Tsirunyan
3
实际上,这个特定案例已经明确提到了:ISO/IEC 14882:2003(E) 第4.1节中的 左值转右值转换 指出,“如果对象未初始化,则需要进行此类型转换的程序具有未定义行为。” - David Hammen
1
@ArmenTsirunyan:对于_Enum,我给出+1,因为它只是一种方便地命名某些值并创建新类型的方式,但您不会通过枚举器的值集来限制枚举的值。 - legends2k
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接