使用try-Catch异常处理程序和if else条件检查之间的区别?

时间:2013-08-19 06:37:42

标签: c++ if-statement exception-handling

我在很多地方使用过if else语句,但我是异常处理的新手。这两者之间的主要区别是什么......

例如:

 int *ptr = new (nothrow) int[1000];

 if (ptr == NULL) {
     // Handle error cases here...
 }

OR

  try
  {
    int* myarray= new int[1000];
  }
  catch (exception& e)
  {
    cout << "Standard exception: " << e.what() << endl; 
  }

所以我们在这里使用标准类的异常,它有一些像e.what这样的构建函数。所以它可能是有利的......除了所有其他功能处理我们可以使用 - 如果否则 - 也。使用异常处理还有其他优点吗?

感谢名单

5 个答案:

答案 0 :(得分:2)

收集评论中的答案:

自1998年标准化以来,new在失败时不返回空指针,但抛出异常,即std::bad_alloc。这与C malloc不同,可能与C ++的一些早期预标准实现不同,其中new 可能也返回NULL(我不知道,tbh)

在C ++中,有可能在分配失败时获得nullpointer而不是异常:

int *ptr = new(std::nothrow) int[1000];

简而言之,您拥有的第一个代码将无法按预期工作,因为它是在存在C ++异常时尝试进行C风格的错误处理。如果分配失败,将抛出异常,永远不会输入if块,并且由于您没有捕获bad_alloc,程序可能会被终止。

有很多文章将一般错误处理与异常vs返回代码进行比较,并且它会在这里尝试涵盖这个主题。其中的例外原因是

  • 函数返回类型不会被错误处理占用,但可以返回实际值 - 不需要“输出”函数参数。
  • 您不需要在每个函数中处理每个函数调用的返回,但可以在调用堆栈的某些级别捕获异常,您实际上可以处理错误
  • 与一个全局errno变量和一个返回的错误代码相比,异常可以将仲裁信息传递给错误处理站点。

答案 1 :(得分:2)

主要区别在于使用异常处理的版本至少可能有效,而使用if语句的版本可能无法正常工作。

您的第一个片段:

int *ptr = new int[1000];

 if (ptr == NULL) {
     // Handle error cases here...
 }

...似乎假设new将在失败的情况下返回空指针。虽然这一次都是正确的,但它并没有处于时间。对于任何合理的当前编译器,new只有两种可能:成功或抛出。因此,您的第二个版本与C ++的工作方式一致。

如果确实想要使用此样式,则可以重写代码以使其在发生故障时返回空指针:

int *ptr = new(nothrow) int[1000];

if (ptr == NULL) {
     // Handle error cases here...
}

在大多数情况下,您不应该直接使用new - 您应该真正使用std::vector<int> p(1000);并完成它。

有了这个,我觉得有必要为很多代码添加它,它可能最有意义的是不做,只是假设内存分配会成功。

有一段时间(MS-DOS),如果你试图分配比可用内存更多的内存,实际上内存分配是相当常见的 - 但这是很久以前的事了。如今,事情并非如此简单(通常)。当前的系统使用虚拟内存,这使情况变得更加复杂。

在Linux上,通常会发生的事情是,即使内存不可用,Linux也会做所谓的“overdcommit”。你仍然会得到一个非空指针,好像分配成功 - 但是当你尝试使用内存时,会发生不好的事情。具体来说,Linux有一个所谓的“OOM杀手”,它基本上假设内存耗尽是一个bug的标志,所以如果它发生,它会试图找到有缺陷的程序,并杀死它/它们。对于大多数实际目的,这意味着您的程序可能会被杀死,而其他(半任意选择的)程序也可能被杀死。

Windows更接近C ++所期望的模型,因此如果(例如)您的代码在无人参与的服务器上运行,则分配可能实际上失败。然而,在它失败之前很长一段时间,它会将机器的其余部分拖到膝盖上,疯狂地交换注定要使分配成功的尝试。如果用户当时正在操作机器,他们通常要么杀死你的程序,要么杀死其他人为你的代码腾出足够的内存来快速获得所请求的内存。

在这些情况中,没有一个是特别现实的,因为假设分配可能会失败。出于大多数实际目的,会发生以下两种情况之一:分配成功或程序死亡。

这导致回到之前的建议:在典型情况下,您通常应该使用std::vector,并假设您的分配成功。如果您需要提供超出该范围的可用性,您只需要以其他方式执行此操作(例如,如果过程重新启动该过程,最好以使用较少内存的方式)。

答案 2 :(得分:2)

如前所述,你原来的if-else示例仍会从C ++ 98开始抛出异常,但添加nothrow(如已编辑)应使其按预期工作(返回null,从而触发if语句。

下面我假设,为了简单起见,对于if-else处理异常,我们在异常时返回false函数。

以上例外的一些优点if-else,在我的头顶:

  • 您知道日志记录/调试/错误修复的异常类型

    示例:

    当函数抛出异常时,您可以在合理的范围内判断代码是否存在问题或者您无法做太多事情,例如内存不足异常。

    使用if-else,当函数返回false时,你不知道该函数发生了什么。

    您当然可以使用单独的日志记录来记录此信息,但为什么不返回包含异常详细信息的异常呢?

  • 你不需要乱七八糟的if-else条件来将异常传播给调用函数

    示例:(包含的注释表示行为)

    bool someFunction() // may return false on exception
    {
       if (someFunction2()) // may return false on exception
          return false;
    
       if (someFunction3()) // may return false on exception
          return false;
    
       return someFunction4(); // may return false on exception
    }
    

    (有很多人不喜欢有多个返回语句的函数。在这种情况下,你的函数会更加混乱。)

    相反:

    void someFunction() // may throw exception
    {
       someFunction2(); // may throw exception
       someFunction3(); // may throw exception
       someFunction4(); // may throw exception
    }
    

if-else的替代或扩展是错误代码。为此,第二点将保留。有关该异常与异常之间的比较的更多信息,请参阅this

答案 3 :(得分:1)

如果您在本地处理错误,if ... else更清晰。如果发生错误的函数不处理错误,则抛出异常以传递给调用链中较高的人。

答案 4 :(得分:0)

首先,if语句的第一个代码将在new []运算符抛出异常的情况下终止程序,因为没有处理异常。您可以在此处查看此类内容,例如:http://www.cplusplus.com/reference/new/operator%20new%5B%5D/

在许多其他情况下也会抛出异常,不仅在分配失败时,它们的主要特征(在我看来)是在应用程序中移动控制(到处理异常的位置)。我建议你阅读更多关于异常的内容,好的阅读将是Scott Meyers的“更有效的C ++”,关于异常的章节很棒。