static_cast可以在C ++中抛出异常吗?

时间:2012-07-18 23:28:22

标签: c++ casting

假设static_cast永远不会抛出异常是否安全?

对于Enum强制转换的int,即使它无效,也不会抛出异常。我可以依靠这种行为吗?以下代码可以使用。

enum animal {
  CAT = 1,
  DOG = 2
};

int y = 10;
animal x = static_cast<animal>(y);

4 个答案:

答案 0 :(得分:13)

对于此特定类型的强制类型(枚举类型的整数),可能会抛出异常。

  

C ++标准5.2.9静态演员[expr.static.cast]第7段

     

可以将积分或枚举类型的值显式转换为   枚举类型。如果原始值为,则该值不变   在枚举值范围内(7.2)。 否则,   结果枚举值未指定/未定义(自C ++ 17起)。

请注意,由于C ++ 17这样的转换实际上可能导致未定义的行为,可能包括抛出异常。

换句话说,如果确保整数通过某些实际表示有效的枚举值,那么使用static_cast从整数中获取枚举值的特定用法就可以了,直到C ++ 17并且总是很好一种输入验证程序。

有时输入验证程序完全不需要static_cast,如下所示:

animal GetAnimal(int y)
{
    switch(y)
    {
    case 1:
        return CAT;
    case 2:
        return DOG;
    default:
        // Do something about the invalid parameter, like throw an exception,
        // write to a log file, or assert() it.
    }
}

请考虑使用类似上述结构的内容,因为它不需要强制转换,并且让您有机会正确处理边界情况。

答案 1 :(得分:10)

  

假设static_cast永远不会抛出异常是否安全?

没有。对于用户定义的类型,构造函数和/或转换运算符可能会抛出异常,从而导致定义明确的行为。

考虑这个程序的输出:

#include <iostream>

struct A {
  A(int) { throw 1; }
};

int main () {
  int y = 7;
  try {
    static_cast<A>(y);
  } catch(...) {
    std::cout << "caught\n";
  }
}

答案 2 :(得分:6)

static_cast不能抛出异常,因为static_cast不是运行时强制转换,如果某些无法转换,代码将无法编译。但是如果它编译并且演员阵容很糟糕 - 结果是不确定的。

答案 3 :(得分:3)

(此答案专注于您问题中的intenum转换。)

  

对于Enum强制转换的int,即使它无效,也不会抛出异常。我可以依靠这种行为吗?以下代码可以使用。

enum animal {   CAT = 1,   DOG = 2 };
int y = 10; 
animal x = static_cast<animal>(y); 

实际上,枚举并不局限于其定义中的枚举列表,这不仅仅是一些奇怪的怪癖,而是故意利用的枚举功能 - 考虑如何将枚举值通常进行OR运算以将它们打包成单个值,当没有任何枚举适用时,或者传递0。

在C ++ 03中,它不是由显式程序员控制编译器将使用多大的后备整数,但保证范围跨越0和明确列出的枚举。

因此,对于animal来说,10不是一个有效的,可存储的值,这不一定是正确的。即使支持值不足以存储您尝试转换为animal的整数值,也可能会应用缩小转换 - 通常这将使用枚举支持类型的许多最低有效位可以保留,丢弃任何额外的高位,但有关详细信息,请查看标准。

实际上,PC和服务器硬件上的大多数现代C ++ 03编译器默认使用(32位)int来支持枚举,因为这有助于调用C库函数,其中32位是常态

我会从不期望编译器在使用static_cast<>将任何值强行插入枚举时抛出异常。