当我尝试除以0时,下面的代码没有捕获到异常。 我需要抛出一个异常,还是计算机在运行时自动抛出一个?
int i = 0;
cin >> i; // what if someone enters zero?
try {
i = 5/i;
}
catch (std::logic_error e) {
cerr << e.what();
}
您需要自己检查它并抛出异常。 整数被零除在标准C++中不是一个例外。
浮点也不能被零除,但至少它有特定的处理方法。
ISO标准中列出的例外情况如下:
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;
}
您可以非常令人信服地认为,overflow_error
(由IEEE754浮点生成的无穷大可以被认为是溢出)或domain_error
(这是输入值的一个问题)对于指示除零是理想的。
然而,5.6
(C++11
的部分,尽管我认为这与上一次迭代没有变化)特别指出:
如果/
或%
的第二个操作数为零,则行为未定义。
因此,它可以抛出这些(或任何其他)异常。 它还可以格式化你的硬盘,嘲笑你:-)
如果您想实现这样的beast,可以在以下程序中使用类似IntDivex
的内容(使用溢出变体):
#include <iostream>
#include <stdexcept>
// Integer division, catching divide by zero.
inline int intDivEx (int numerator, int denominator) {
if (denominator == 0)
throw std::overflow_error("Divide by zero exception");
return numerator / denominator;
}
int main (void) {
int i = 42;
try { i = intDivEx (10, 2); }
catch (std::overflow_error e) {
std::cout << e.what() << " -> ";
}
std::cout << i << std::endl;
try { i = intDivEx (10, 0); }
catch (std::overflow_error e) {
std::cout << e.what() << " -> ";
}
std::cout << i << std::endl;
return 0;
}
此输出:
5
Divide by zero exception -> 5
您可以看到它抛出并捕获除零情况下的异常。
等效的%
几乎完全相同:
// Integer remainder, catching divide by zero.
inline int intModEx (int numerator, int denominator) {
if (denominator == 0)
throw std::overflow_error("Divide by zero exception");
return numerator % denominator;
}
使用ExcessPhase中的注释更新
GCC(至少4.8版)将允许您模拟这种行为:
#include <signal.h>
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<void(int)> handler(
signal(SIGFPE, [](int signum) {throw std::logic_error("FPE"); }),
[](__sighandler_t f) { signal(SIGFPE, f); });
int i = 0;
std::cin >> i; // what if someone enters zero?
try {
i = 5/i;
}
catch (std::logic_error e) {
std::cerr << e.what();
}
}
这将设置一个抛出异常的新信号处理程序和一个shared_ptr
到旧信号处理程序,并使用一个自定义的“deletion”函数在旧处理程序超出作用域时还原旧处理程序。
您至少需要使用以下选项进行编译:
g++ -c Foo.cc -o Foo.o -fnon-call-exceptions -std=c++11
Visual C++还允许您执行类似的操作:
#include <eh.h>
#include <memory>
int main() {
std::shared_ptr<void(unsigned, EXCEPTION_POINTERS*)> handler(
_set_se_translator([](unsigned u, EXCEPTION_POINTERS* p) {
switch(u) {
case FLT_DIVIDE_BY_ZERO:
case INT_DIVIDE_BY_ZERO:
throw std::logic_error("Divide by zero");
break;
...
default:
throw std::logic_error("SEH exception");
}
}),
[](_se_translator_function f) { _set_se_translator(f); });
int i = 0;
try {
i = 5 / i;
} catch(std::logic_error e) {
std::cerr << e.what();
}
}
当然,你可以跳过所有的C++11,把它们放到一个传统的rai-management结构中。
据我所知,C++规范中没有提到任何关于除零的内容。 我相信你需要自己做。。。
Stroustrup在《the Design and Evolution of C++》(Addison Wesley,1994)中说:“低级事件,如算术溢出和除零,被认为是由一个专用的低级机制而不是由异常来处理的。这使得C++在涉及算术时能够匹配其他语言的行为。它还避免了在严重流水线结构中发生的问题,其中除零等事件是异步的。”