抛出或不抛出异常?

Bru*_*ero 10 c++

我正在和我的一个朋友谈话,通过我的新代码,我没有处理异常,只是因为我不知道如何在C++中这样做.他的回答让我感到惊讶:"为什么你想要抛出异常?" 我问他为什么,但他没有一个令人满意的答案,所以我用Google搜索.我找到的第一个页面之一是博客文章,发布的人并非完全反对例外,但在回复中开始了宗教战争:http://weblogs.asp.net/alex_papadimoulis/archive/2005/03 /29/396141.aspx

现在我开始怀疑:抛出异常是不是很糟糕?对于像我这样的学生来说,使用异常学习编程是不正常的吗?(当我抛出异常时,我会在代码的另一个级别捕获它们,大多数时候都会对它们进行处理).我有一个代码示例,我想知道我该怎么做:

int x;
cout << "Type an integer: ";
cin >> x;
Run Code Online (Sandbox Code Playgroud)

那里输入的任何不是整数的东西都会触发异常,对吧?这个例外应该在那里处理.但是当我在一个正在程序中其他地方使用的类中有一个可能的异常时,我应该让这个方法抛出一个异常,这样我可以在任何我调用它的地方处理它,或者我应该在它有任何问题时返回一个标准值?

例外总是好的,总是坏的,或者在"特殊"情况下使用的东西?为什么?

Mic*_*yan 13

默认情况下,C++ iostreams类不使用异常处理.通常,应该对可能发生错误的情况使用异常,但这种错误是"异常"和"不常见"(例如磁盘发生故障,网络发生故障等).对于您期望的错误条件(例如用户提供无效输入),您可能不应该使用异常处理,除非需要处理此情况的逻辑远离检测到情境的逻辑,其中使用例外的情况是要走的路.使用异常并没有任何问题,并且在使用异常的情况下使用异常绝对是好的...只要避免使用它们,如果......其他工作正常.

至于原因:

  1. 例外通常提供一种处理意外错误的简单,优雅的方法,但是:
  2. 异常传播,取决于编译器和平台,可能比普通控制流慢,所以如果你可以在本地处理这种情况,那么这将至少同样快......你特别不想放慢常见的速度,预期案例(如无效输入).也:
  3. 异常需要存在更多类型信息,并且还需要与抛出或捕获异常无关的代码为"异常安全",这就是为什么某些异常对象的原因.

  • +1 - 请注意,即使您不使用异常,也应该尝试编写异常安全代码,以便在与*使用异常的代码混合时使代码正常运行. (3认同)
  • 我要添加一个#4:例外可以使分析程序流程变得更加困难.这和异常使用有毒的事实(你不能只是部分使用它们)是AFAIK反对的更常见的背景. (3认同)
  • @George Fritzsche:比什么更难?如果您没有使用异常,则需要使用其他方法将错误信息传播回某个控制点.如果您使用错误代码(最流行的技术),我会说程序流更容易分析,而不是错误代码.但是,异常比零错误检查代码更难分析,但不是很有用. (2认同)

Mar*_*ork 9

问题1:

没有理由不使用例外.
是否使用例外或其他技术取决于具体情况.

当您无法在本地修复错误时,可以使用例外.
(这应该是特殊情况:-)

当您可以在本地修复错误时,错误代码很好.

如果您有一个库,该库公开一个返回需要手动检查的错误代码的接口,则错误代码是错误的.在C世界中,忘记检查错误代码是一个重要的问题来源.

如果要强制界面用户检查错误,则例外情况很好.如果用户没有明确检查和补偿; 然后异常将传播,直到它被处理或应用程序退出.

异常带来的问题:
如果您的代码是C和C++的组合.具有C ABI的函数不包含足以传播异常的信息.因此,在C函数中抛出异常可能(取决于编译器和其他因素)会导致问题.

如果使用使用C++代码的C库注册回调函数.然后,您必须确保所有异常都在回调函数中捕获,并且不允许传播回C库.

但是当结合任何两种语言时都是如此.您只能跨语言边界使用最原始的功能(如果语言不能很好地对齐,甚至可以使用这些功能).因此,通常不支持尝试使用任何高级功能.

问题2:

默认情况下,C++流不使用异常.
这是因为通常您希望立即处理问题.

在您的示例中,您使用输入作为示例.在这种情况下,您要检查错误并重新请求输入.

int x;
cout << "Type an integer: "; 
cin >> x;
while(!cin)
{
    cin.clear();
    std::cout << "Failed: What do you think an integer is? Try again: ";
    cin >> x;
}
Run Code Online (Sandbox Code Playgroud)

注意:

我个人不喜欢"在特殊情况下使用异常"这个短语.对我来说只是模糊.vector :: at()抛出一个异常.对于我来说,访问一个数组的末尾将是例外(但是对于乔学生,我怀疑它会是特殊的(当讲师向他/她投掷一个新的曲线球时,它会发生在每一个二等级)).

因此,我更喜欢"当问题无法在当地修复"时.一个无法在本地修复的问题是当一个大问题出现时(资源耗尽(内存全抛bad_alloc()),编码错误(超出数组边界的访问(throw range_check())))或任何不能解决的问题固定在那里.