何时以及如何使用异常处理?

我正在阅读关于异常处理的文章。我得到了一些关于什么是异常处理的信息,但是我有几个问题:

  1. 何时引发异常?
  2. 我们可以使用返回值来指示错误而不是抛出异常吗?
  3. 如果我使用 try-catch 块来保护所有的函数,不会降低性能吗?
  4. 何时使用异常处理?
  5. 我看到一个项目,该项目中的每个函数都包含一个 try-catch 块(也就是说,整个函数中的代码都被 try-catch 块包围)。这是个好习惯吗?
  6. Try-catch 和 _ _ try _ _ but 有什么区别?
45811 次浏览

1.An exception check is included in the code when there is a possibility of getting an exception as a result or somewhere in between the problem.

2.Use try-catch block with only those cases where it is required. Usage of each try-catch block add to an extra condition check that certainly reduces the optimization of the code.

3.I think _try_except is a valid variable name....

Many C/C++ purists discourage exceptions altogether. The main criticisms are:

  1. It's slow - Of course it isn't really "slow". However, compared to pure c/c++, there is quite a bit of overhead.
  2. It introduces bugs - If you don't handle exceptions properly, you can miss the clean-up code in the function that throws the exception.

Instead, check the return value / error code every time you call a function.

The basical difference is:

  1. one make error handling for you.
  2. an one is you do your own.

    • For instance, you have an expression could make 0 divide error. Using try catch 1. will help you when error occurred. Or you need an if a==0 then.. in 2.

    • If you dont try catch the exception I dont think its faster, its just simply bypass, if error occurred it will be threw to an outer handler.

Handing yourself mean the problem not go further then have advantage in speed in many case, but not always.

Suggest: Just handling yourself when it simple and in logically case.

Here's quite comprehensive guide on exceptions that I think is a Must Read:

Exceptions and error handling - C++ FAQ or C++ FAQ lite

As a general rule of thumb, throw an exception when your program can identify an external problem that prevents execution. If you receive data from the server and that data is invalid, throw an exception. Out of disk space? Throw an exception. Cosmic rays prevent you from querying the database? Throw an exception. But if you get some invalid data from inside your very own program - don't throw an exception. If your problem comes from your own bad code, it's better to use ASSERTs to guard against it. Exception handling is needed to identify problems that program cannot handle and tell them about the user, because user can handle them. But bugs in your program are not something the user can handle, so program crashing will tell not much less than "Value of answer_to_life_and_universe_and_everything is not 42! This should never happen!!!!11" exception.

Catch an exception where you can do something useful with it, like, display a message box. I prefer to catch an exception once inside a function that somehow handles user input. For example, user presses button "Annihilate all hunams", and inside annihilateAllHunamsClicked() function there's a try...catch block to say "I can't". Even though annihilation of hunamkind is a complex operation that requires calling dozens and dozens of functions, there is only one try...catch, because for a user it's an atomic operation - one button click. Exception checks in every function are redundant and ugly.

Also, I can't recommend enough getting familiar with RAII - that is, to make sure that all data that is initialized is destroyed automatically. And that can be achieved by initializing as much as possible on stack, and when you need to initialize something on heap, use some kind of smart pointer. Everything initialized on the stack will be destroyed automatically when an exception is thrown. If you use C-style dumb pointers, you risk memory leak when an exception is thrown, because there is noone to clean them up upon exception (sure, you can use C-style pointers as members of your class, but make sure they are taken care of in destructor).

Exceptions are useful in a variety of circumstances.

First, there are some functions where the cost of calculating the pre-condition is so high it is better to just do the calculation and abort with an exception if it is found the pre-condition is not met. For example, you cannot invert a singular matrix, however to calculate if it is singular you calculate the determinant which is very expensive: it may have to be done inside the function anyhow, so just "have a try" at inverting the matrix and report an error if you can't by throwing an exception. This is basically an exception as negative pre-condition usage.

Then there are other cases where your code is already complex and passing error information up the call chain is difficult. This is partly because C and C++ have broken data structure models: there are other, better ways, but C++ doesn't support them (such as using monads in Haskell). This use is basically I couldn't be bothered to do it right so I'll throw an exception: its not the right way but it's practical.

Then there is the main use of exceptions: to report when external pre-conditions or invariants, such as sufficient resources like memory or disk space, are not available. In this case you will usually terminate the program, or a major subsection of it, and the exception is a good way of transmitting information about the problem. C++ Exceptions were designed for reporting errors which prevent the program continuing.

The exception handling model used in most modern languages including C++ is known to be broken. It is vastly too powerful. Theoreticians have now developed better models than the completely open "throw anything" and "maybe and maybe not catch it" model. In addition using type information to classify exceptions wasn't a very good idea.

So the best thing you can do is throw exceptions sparingly, when there's an actual error, and when there's no other way to deal with it and catch exceptions as close to the throw point as possible.

Best read for this

Exception handling has been talked about a lot over the last decade and a half. However, despite a general consensus on how to properly handle exceptions, a divide on usage continues to exist. Improper exception handling is easy to spot, easy to avoid, and is a simple code (and developer) quality metric. I know absolute rules come off as close minded or exaggerated, but as a general rule you shouldn’t be using try/catch

http://codebetter.com/karlseguin/2010/01/25/don-t-use-try-catch/

If your problem comes from your own bad code, it's better to use ASSERTs to guard against it. Exception handling is needed to identify problems that program cannot handle and tell them about the user, because user can handle them. But bugs in your program are not something the user can handle, so program crashing will tell not much

I disagree with this aspect of the accepted answer. An assert is not hands-down better than throwing an exception. If exceptions were suitable only for run-time errors (or "external problems") , what is std::logic_error for?

A logic error is almost by definition the kind of condition that prevents a program from continuing. If the program is a logical construct, and a condition occurs outside the domain of that logic, how can it continue? Gather ye inputs while ye may, and throw an exception!

It's not like there's not prior art. std::vector, to name but one, throws a logic error exception, namely std::out_of_range. If you use the standard library and don't have a top-level handler to catch standard exceptions -- if only to call what() and exit(3) -- then your programs are subject to abrupt silent, termination.

An assert macro is a much weaker guard. There is no recovery. Unless, that is, you're not running a debug build, in which case there's no execution. The assert macro belongs to an era when computation was 6 orders of magnitude slower than today. If you're going to the trouble to test for logic errors, but not to use that test when it counts, in production, you'd better have a lot of confidence in your code!

The standard library provides for logic error exceptions, and employs them. They are there for a reason: because logic errors occur, and are exceptional. Just because C features assertions is no reason to rely on such a primitive (and, arguably, useless) mechanism, when an exception handles the job so much better.