为什么 C++ 中没有预定义的零除异常?

utg*_*awg 1 c++

标准(我使用的是 ISO C++17)中有详细记录ISO C++,整数除以 0 的结果是未定义的。这也可以从头中可用的预定义异常列表中排除零除异常看出<stdexcept>

namespace std {
    class logic_error;
    class domain_error;
    class invalid_argument;
    class length_error;
    class out_of_range;
    class runtime_error;
    class range_error;
    class overflow_error;
    class underflow_error;
}
Run Code Online (Sandbox Code Playgroud)

虽然我知道被调用函数只能检查除数是否为 0 并抛出domain_erroror overflow_error,但我想知道没有预定义零除异常的可能原因是什么。

use*_*522 7

(几乎)没有任何核心语言结构会抛出异常(throw当然除外)。该规则的唯一例外是newwhich may throw a std::bad_array_new_lengthdynamic_cast它显式地具有抛出和非抛出形式,并且typeid它可能抛出std\xe2\x80\x8b::\xe2\x80\x8bbad_typeid

\n

引发异常是一项成本高昂的操作,而使用 C++ 的首要原因之一是性能。强制程序在每次除法时都进行空值检查然后抛出异常是没有意义的。如果有人想要,他们可以将其包装在自己的函数中以代替内置的除法运算符。

\n

在上面列出的异常中,操作本身的成本就已经很高,因此抛出异常是可以接受的。

\n

核心语言必须尽可能具有性能。如果需要的话,其他一切都可以在库函数中完成。

\n

  • @utg.tdawg 要了解操作的成本,您需要(至少粗略地)了解它们的实现方式:访问向量元素通常只是一条“mov”指令,其位置是通过在基数上添加索引来计算的指针。如果添加边界检查,则必须引入一个分支,并在分支的一侧引入异常(调用 C++ 运行时库来展开堆栈 -&gt; 有很多工作要做)。 (3认同)
  • @utg.tdawg 另一方面,“new”已经很昂贵,因为它调用分配器来分配内存,这通常是一项相当复杂的任务,并且本身可能已经因分配失败而抛出。`typeid` 和 `dynamic_cast` 使用 RTTI,这已经相当复杂了。 (3认同)