When catching an exception the standard guidance is to throw by value, catch by reference. As I understand it, this is for two reasons:
- If the exception was thrown due to an out of memory exception, we won’t call a copy constructor which could potentially terminate the program.
- If the exception is part of an inheritance heirarchy, we may potentially have object slicing on the exception.
If we have a scenario where we don’t define the exception name in the catch block are these concerns (really 1., as slicing won’t be an issue if we don’t have a name for the variable) still valid?
For example:
catch(my_exception)
{ ... }
or
catch(my_exception &)
{ ... }
Is there still the possibility of the program terminating if the exception caught by value in this case? My feeling is that it is technically still possible.
Note: I am asking this because I have had to review someone’s code who put a catch by value in this case. As shown in the question I am not entirely sure on the technical impact of either choice, but I think that in terms of consistancy it is better to catch by reference in this case regardless (there is no downside to catching by reference in any case).
The standard does not require special optimization in the case of an unnamed exception object. On the contrary, it then requires an effect as if a temporary is copy-initialized. This copying can result in memory being dynamically allocated.
The paragraph above does not mention catching by reference, and so one might reasonably conclude that it applies whether or not the exception object is caught by reference; that a copy is constructed anyway.
However, that is contradicted by the next paragraph:
So, declared type
T&(withTnon-const) is the single case where C++11 requires a reference directly to the thrown object, instead of copying. And it is also that way in C++03, except that C++03 has some additional wording about as-if optimization. So, for the formal the preference should be forand
However, I have always caught exceptions like
catch( T const& ). From a practical point of view one may assume that the compiler will optimize that to a direct reference to the thrown object, even though it is possible to devise cases where the observed program effect would then be non-standard. For example<evil grin>With both MinGW g++ 4.4.1 and Visual C++ 10.0 the output is …
A pedantic formalist might say that both compilers are non-conforming, failing to create a copy for the
Error const&case. A purely practical practitioner might say that hey, what else did you expect? And me, I say that the wording in the standard is very far from perfect here, and that if anything, one should expect a clarification to explicitly allow the output above, so that also catching by reference toconstis both safe and maximally efficient.Summing up wrt. the OP’s question:
Catching by reference won’t call a copy constructor which could potentially terminate the program.
The standard only guarantees this for reference to non-
const.In practice, as shown, it is also guaranteed for reference to
const, even when program results are then affected.Cheers & hth.,