Exceptions | 异常👀
约 357 个字 162 行代码 预计阅读时间 3 分钟
Vector
T &operator[](int i);
是可能发生越界的,如何处理:-
Choice:
- Return random memory object —
return elem[i];
-
Return a special error value
if(i < 0 || i >= size()) { // WRONG - T 不一定有这种构造函数,且原本就可能有这样正常的内容 T *error_marker = new T("some magic value"); return *error_marker; } return elem[i];
- But this throws the baby out with the bath!
x = v[2] + v[4]; //Not safe code
-
Just die!
-
Die gracefully (with autopsy)
assert
做接口检查,在调用函数时会检查传入参数是否合法,若不合法则直接退出程序
- Return random memory object —
- When to use exceptions?
- Many times, you don’t know what should be done
- Solution: turf the problem to the caller | 将问题向上报
- Make caller responsible for handling the problem
throw
| 抛出异常👀
-
How to raise an exception —
throw
-
What do you throw?
- What do you have? ← Data
- Define a class to represent the error
-
How to raise it?
-
What about your caller
-
Case 1) Don’t care — Code never even suspects a problem
-
Case 2) Care deeply
-
Case 3) Mildly interested
-
Case 4) Doesn’t care about the particulars (
...
means “catch All exceptions” )
-
Review
- Throw statement raises the exception
- Control propagates back to first handler for that exception
- Propagation follows the call chain
- Objects on stack are properly destroyed
throw exp
;- throws value for matching
throw
;- reraises the exception being handled
- valid only within a handler
Exception Handlers👀
-
Try block
try { // code that might throw an exception } catch ... { // code that handles the exception } catch ... { // code that handles the exception }
- Establishes any number of handlers
- Not needed if you don’t use any handlers
- Shows where you expect to handle exceptions
- Costs cycles
-
Exception handlers
- Select exception by type
- Can re-raise exception
- Two forms
catch (Type)
catch (...)
- Take a single argument (like a formal parameter)
-
Selecting a handler
- Can have any number of handlers
- Handlers are checked in order of appearance
1. Check for exact match
2. Apply base class conversions (Reference and pointer types, only)
3. Ellipses(…) matches any exception
-
Inheritance can be used to structure exceptions
using inheritance
- Hierachy of exception types
-
Exception and new
- new does NOT return 0 on failure
- new raises a bad_alloc exception on failure
-
Exception specifications
- Declare which exceptions a function might throw
- Part of function prototypes
- Not checked at compile time
- At run time, if an exception not in the list propagates out, the
unexpected
exception is raised
Failure in Ctors & Dtors👀
Failure in Ctors👀
- No return value is possible
- Use an “uninitialized” flag
- Defer work to an Init() function
-
Better to throw an exception
-
If a constructor can’t complete, throw an exception
- Dtors for objects whose ctor didn’t complete won’t be called
- Clean up allocated resources before throwing
Suggest - Two stages construction
- Do normal work in ctor
- Initialize all member objects
- Initialize all primitive members
- Initialize all pointers to 0
- NEVER request any resources
- File / Network connection / Memory
- Do additional work in Init() function
- Request resources
- Do any other work that might fail
Failure in Dtors👀
Destructors are called when:
- Normal call: object exists from scope
-
During exceptions: stack unwinding invokes dtors on objects as scope is existed
-
Throwing an exception in a dtor that is itself being called as the result of an exception will invoke
std::terminate()
- Allowing exceptions to escape from dtors should be avoided
catch
catch
exceptions by reference or pointercatch(BUG *e)
— we needdelete e
in the handlercatch(BUG &e)
— we need care when to destructe