我正在阅读有关异常处理的内容。我已经了解了什么是异常处理,但是还有一些问题:
- 什么时候抛出异常?
- 除了抛出异常,我们是否可以使用返回值来指示错误?
- 如果我将所有函数都用try-catch块保护起来,这不会降低性能吗?
- 何时使用异常处理?
- 我看到一个项目中每个函数都包含一个try-catch块(即整个函数的代码都被try-catch块包围)。这是一个好的实践吗?
- try-catch和__try __except之间的区别是什么?
我正在阅读有关异常处理的内容。我已经了解了什么是异常处理,但是还有一些问题:
这是一份相当全面的关于异常处理指南,我认为它是必读的:
异常和错误处理 - C++ FAQ 或者 C++ FAQ lite
通常情况下,当你的程序可以识别一个阻止执行的外部问题时,抛出异常。如果从服务器接收到无效数据,则抛出异常。磁盘空间不足?抛出异常。宇宙射线阻止你查询数据库?抛出异常。但如果你从自己的程序内部获得了一些无效数据,就不要抛出异常。如果你的问题来自于自己糟糕的代码,最好使用ASSERT来防范。异常处理是为了识别程序无法处理的问题并告诉用户,因为用户可以处理它们。但是程序中的错误不是用户能够处理的,因此程序崩溃并不比"answer_to_life_and_universe_and_everything的值不是42!这不应该发生!!!11"异常少多少。
在你能够有所作为的地方捕获异常,比如显示一个消息框。我更喜欢在某个处理用户输入的函数中捕获一次异常。例如,用户按下"Annihilate all hunams"按钮,在annihilateAllHunamsClicked()函数内部有一个try...catch块来告诉用户"我不能这样做"。即使消灭人类是一个需要调用数十个函数的复杂操作,只有一个try...catch块,因为对于用户来说它是一个原子操作 - 一个按钮点击。每个函数内的异常检查是冗余而且难看的。
此外,我强烈建议熟悉RAII - 即确保所有初始化的数据都可以自动销毁。这可以通过尽可能在堆栈上初始化,以及在需要在堆上初始化时使用某种智能指针来实现。在堆栈上初始化的所有内容都将在抛出异常时自动销毁。如果使用C风格的愚笨指针,则在抛出异常时有可能导致内存泄漏,因为没有人可以在异常时清理它们(当然,您可以将C风格指针用作类成员,但请确保在析构函数中处理它们)。
fclose
析构函数!)。它也不会给你完整的堆栈跟踪。 - user4266696异常在各种情况下都非常有用。
首先,有些函数计算前置条件的成本太高了,如果发现前置条件不满足,最好只是计算并通过抛出异常中止操作。例如,您无法反转奇异矩阵,但是为了计算它是否奇异,需要计算行列式,这非常昂贵:它可能必须在函数内部完成,因此只需“尝试”反转矩阵,并在无法反转时通过抛出异常报错。这基本上是使用 负前置条件异常。
然后还有其他情况,其中您的代码已经很复杂,并且将错误信息传递到调用链上很困难。这部分原因是 C 和 C++ 的数据结构模型已经损坏:有其他更好的方式,但 C++ 不支持它们(例如,在 Haskell 中使用单子)。这种用法基本上是 我不想正确处理,所以就抛出异常:这不是正确的方法,但这是实际的方法。
然后,异常的主要用途是报告外部前置条件或不变量,例如内存或磁盘空间等资源不足的情况。在这种情况下,通常会终止程序或其主要子部分,异常是传递有关问题信息的好方法。 C++ 异常设计用于报告阻止程序继续运行的错误。
大多数现代语言使用的异常处理模型(包括 C++)被认为是不完善的。它的强大程度过于夸张。理论家们现在已经开发出了比完全开放的“抛出任何东西”和“可能也可能不捕获它”的模型更好的模型。此外,使用类型信息对异常进行分类并不是一个很好的想法。
因此,您最好只在实际错误时且没有其他处理方式时抛出异常,并尽可能靠近抛出点处捕获异常。
std::logic_error
有什么作用呢?std::vector
为例,它抛出一个逻辑错误异常,即std::out_of_range
。如果你使用标准库并且没有顶层处理程序来捕获标准异常——即使只是调用what()和exit(3)——那么你的程序就会突然而静默地终止。最佳阅读材料
异常处理在过去的十五年中一直备受关注。然而,尽管对于如何正确处理异常存在普遍共识,但使用方式上仍然存在分歧。不正确的异常处理很容易被发现,也很容易避免,是一个简单的代码(和开发者)质量指标。我知道绝对规则会显得固执或夸张,但通常情况下你不应该使用try/catch。
http://codebetter.com/karlseguin/2010/01/25/don-t-use-try-catch/
try
/catch{}
吗? - Craig McQueen1. 当代码存在异常可能性或者问题中间可能出现异常时,需要在代码中包含异常检查。
2. 只有在必要的情况下使用try-catch块。每个try-catch块的使用都会增加额外的条件检查,这肯定会降低代码的优化程度。
3. 我认为_try_except是一个有效的变量名....
基本区别是:
另一个是你自己处理。
例如,你有一个可能会导致 0除以错误
的表达式。使用 try catch 1.
将会在发生错误时帮助你。或者你需要在 2.
中使用 if a==0 then..
如果你不使用 try catch 来捕获异常,我认为它并非更快,只是简单地绕过了,如果出现 error
,它将被 抛出
到外部处理程序。
自行处理意味着问题不会进一步扩大,在许多情况下具有速度优势,但并非总是如此。
建议:在简单且逻辑清晰的情况下,仅自行处理。
相反,每次调用函数时请检查返回值/错误代码。