What is be开发者_运维知识库tter coding practice: if I have to have a try/catch block shall I place everything (every initialization and so on) in this block or just those variables which may throw? Is there any difference between those two constructions?
In example:
Having:struct A {
A();
int a;
int* b;
};
and later on in .cpp:
A::A() {
a = 5;
try {
b = new int;
}
catch(...){
}
}
or
A:A() {
try {
a = 5; //this time in try block
b = new int;
}
catch(...) {
}
}
is there any difference between those two constructs or is this in a way if I have to have a try/catch block I may aswell put everything in it? Thank you.
P.S. For God efin sake, formatting here drives me really crazy! And I know that I mentioned this many times, I'm not going mad.
I think a good general principle is to make a try
block as "narrow" as possible -- don't put in it things that you believe won't ever cause exceptions. That way, should you ever be wrong and have one of those "can't cause exception" parts actually do cause an exception, you won't be accidentally "swallowing" the astonishing exception (and no doubt dealing with it in inappropriate ways, since your code would not be expecting that exception but other kinds).
In your code, I would not use a try block at the point you indicate at all. Memory allocation errors are actually both very rare and very difficult to recover from. I would probably catch the exception in main, log the error and exit the program.
More broadly, in C++ you should not wrap every function that could throw in a try block. You should instead write code that can cope with exceptions, using well-known C++ idioms like RAII.
In addition to the very good points by Alex and Neil, the narrow try block makes for an easier to understand code. A future maintainer will know more easily what's going on.
@ Alex,
I disagree. You should group logical parts of your program into try catches that should fail or pass as a whole. If something fails, even if you didn't expect it your code should be exception safe and the whole operation should fail and all resources should automatically be released. If you make them narrow then you just end up with tons and tons of try's and catches. Why not just use IF's? (but wasn't that the point of exceptions in the first place? avoid tons of ifs?)
Parashift agrees with me too.
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.12
read 17.12 and 17.13.
Another way to look at this is to include statements in a try block when they all need to succeed or fail together. This way, catch blocks act as a kind of transactional feature in your code. So, you can do something like:
// save current state
try {
// a few statements
// that each modify the state
} catch (e) {
// rollback to original state
}
In your example, assigning to member variable a changes the state of the object, so it should be inside the try block.
In my code, I rarely ever catch anything, except in main()
. If you feel like you need catch
blocks to clean up after yourself, you do something wrong and need to have a good look at the RAII idiom. As for anything else - an exception should be thrown under exceptional circumstances only, and it's very hard to come up with something generic and smart to do in exceptional moments.
精彩评论