5

所以我写了一些代码,我注意到,除了语法,类型和其他编译时错误,C++不会抛出任何其他异常。所以我决定用一个非常重要的程序测试了这一点:C++异常处理

#include<iostream> 

int main() { 
    std::count<<5/0<<std::endl; 
return 1 
} 

当我用G ++编译它,G ++给了我一个警告,说我被划分为0但它仍然编译的代码。然后当我运行它时,它会打印一些非常大的任意数字。当我想知道的是,C++如何处理异常?应该是一个非常简单的例子,当抛出异常并且程序应该终止时。

我是否必须将我的整个程序封装在一个巨大的try块中,然后捕获某些异常?我在Python中知道抛出异常时,程序将立即终止并打印出错误。 C++是做什么的?是否有运行时异常停止执行并终止程序?

回答

8

存在运行时异常,但并非所有“错误”都会导致运行时异常被抛出。例如,获取数组越界或解引用空指针就是“未定义行为” - 意味着任何事情都可能发生。除零也属于“未定义”类别。

导致“未定义行为”而非异常的一些操作的基本原理是效率。假设超出界限的数组访问需要抛出异常。然后,编译器必须为每个数组访问生成代码,以检查它是否超出范围,如果是,则引发异常。这是很多检查,其中大部分是不必要的。相反,编译器所做的只是为元素访问生成指令,假设它处于边界内。如果碰巧出界,则发生任何事情(例如分段故障)。如果你想想要进行检查,你总是可以明确地编码。

这使得C++比总是进行检查的语言(例如Java或python)更强大,因为您可以选择何时需要检查,何时不检查。 (另一方面,它使C++不如Java或python安全,这是一种折衷)。


至于什么时候抛出一个异常,但没有在任何地方陷入发生什么事,通常编译器实现将打印包含错误信息的异常的what()。在你的例子中,这是不适用的,因为没有抛出运行时异常。

+0

谢谢,这是有道理的。另一个问题。如果不是使用std :: cout,我使用std :: cerr,会抛出异常,还是只打印到错误流?如果我创建自己的异常(可以说foo),并且在我的代码中,我会说throw foo,那么我的程序是否会立即被杀死,并且foo.what()会被打印出来?还是我必须明确告诉C++这样做? – user1413793

+0

@ user1413793:如果你写入'std :: cerr',它只会打印到错误流。您可以通过命令行('>'vs'2>')通过重定向将输出流和错误流发送到不同的地方。如果你抛出一个异常,并且你没有在任何地方捕捉到它,程序将立即终止并打印一条错误消息。 (更确切的说,一个名为'std :: terminate'的函数将被调用,它的默认行为是终止程序并打印异常的消息。你可以通过调用'std :: set_terminate'来覆盖行为。有兴趣。) – HighCommander4

0

Visual C++将此标记正确地标记为零除错误。所以如果它不编译,那么运行它就没有问题了。

+0

但它是 “正确”?只是好奇。 –

+0

甚至在任何标准之前,除以零都是未定义的,对吗? – Superman

3

是的,有运行时异常。一个示例是out_of_range,它由vector::at引发。

然而,除以零是未定义的(C++ 0X§5.6/ 4):

如果/或%所述第二操作数是零的行为被理解过程音响定义。

因此,它可能无法编译,抛出一个伪造的异常,打印“一些非常大的任意数字”或段错误。

+0

好的,谢谢!我只是困惑,因为其他语言抛出异常,但这是有道理的:) – user1413793

2

C++只抛出在C++标准中定义明确的标准异常。(是它包括了一些运行时异常

整型除以零不是一个标准C++异常(技术上它是未定义行为)。所以不会引发隐式异常。一个特定的编译器可能会将运行时错误映射为某种异常(您需要检查编译器文档中是否有这种情况,有些编译器映射除以零来表示某种异常),如果是这样,您可以捕获该特定异常。但是请注意,这不是可移植的行为,不适用于所有编译器。

最好你可以做的是自己检查错误条件(除数等于零),并在这种情况下显式抛出一个异常。

编辑:要根据标准答案的评论

class A 
{ 
    public: 
     void f() 
     { 
      int x; 
      //For illustration only 
      int a = 0; 
      if(a == 0) 
        throw std::runtime_error("Divide by zero Exception"); 
      x=1/a; 
     } 

     A() 
     { 
       try 
       { 
        f(); 
       } 
       catch(const std::runtime_error& e) 
       { 
        cout << "Exception caught\n"; 
        cout << e.what(); 
       } 
     } 
};  
+0

会抛出异常导致程序终止并打印出异常,或者我必须接着捕捉异常并明确告诉C++该怎么做? – user1413793

+1

@ user1413793:更新了答案。您必须捕捉异常并决定如何处理。 –