c++ - 为什么我从 enum 到 int 的转换在发布版本中不起作用?

标签 c++ casting enums

我发现以下代码在调试版本中工作正常,但在发布时不正确:

enum FileFormatDetection
{
    Binary,
    ASCII,
    Auto
};

FileFormatDetection detection_mode = (FileFormatDetection)ReadIntKey(NULL, KEY_ALL, "FIL_ASCIIORBINARY", -1); // Assigns -1, as confirmed by debug output
if (detection_mode < 0 || detection_mode > 2)
{
    // Not a valid value, so set to default:
    detection_mode = Auto;
}

在每个构建中,调试输出确认该值为 -1。在调试版本中,值 -1 导致进入 if 分支;在发布时,它没有。

我试过如下将 detection_mode 转换为 int:

if ((int)detection_mode < 0 || (int)detection_mode > 2)

和:

if (int(detection_mode) < 0 || int(detection_mode) > 2)

但两者都没有任何区别。

我能做到这一点的唯一方法是将枚举变量转换为整数堆栈变量并测试:

int detection_int = (int)detection_mode;
if (detection_int < 0 || detection_int > 2)
{
    ...

现在,如预期的那样进入 if 分支。

我不明白为什么这是必要的 - 我仍然认为原始代码(或至少测试临时 Actor )应该有效。谁能解释为什么没有?

最佳答案

问题在于,当您将不是枚举器之一的值分配给枚举时,强制转换会导致未定义的行为。

当您在 Release模式下编译时,优化器会看到以下表达式:

if (detection_mode < 0 || detection_mode > 2)

并且知道 detection_mode 的类型是 FileFormatDetection,它知道该特定枚举的所有有效值都在范围内,因此 if 语句永远不会是 >true(至少在一个定义良好的程序中)所以它完全删除了 if

if 中转换为 int 将无济于事,因为同样的推理仍然适用:转换前的值(同样在定义良好的程序中)是在 [0..2] 范围内,因此优化器会删除 if。重要的是要注意,转换是否显式并不重要,因为枚举将被转换为 int 以在两种情况下进行比较。

如果您将值存储在 int 中,那么一切都会改变。有不少 int 值落在该范围之外,因此必须执行比较。另请注意,通过此更改,程序变得定义明确,因为 -1 有效的 int。这实际上是您应该做的:获取作为 int 的值,并且仅当它可以转换为枚举时,才执行转换。

关于c++ - 为什么我从 enum 到 int 的转换在发布版本中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11509214/

相关文章:

java - 我可以将字符串转换为具有泛型类型的列表吗?

java - 枚举实例内的异常处理

java - 如何使用枚举为对象分配标志

c++ - Qt和串口编程

c++ - "Capture by move"不阻止引用捕获

c++ - 调用模板函数时出现歧义

java - 无法从 object 转换为int

python - 基数为 10 的 int 的无效文字 : ''

java - 创建每个值都指向字符串列表的枚举时出错

c++ - 是否可以 boost::bind 到已知类但(尚)未知对象的成员函数?