105

I've heard and read many times that it is better to catch an exception as reference-to-const rather than as reference. Why is:

try {
    // stuff
} catch (const std::exception& e) {
    // stuff
}

better than:

try {
    // stuff
} catch (std::exception& e) {
    // stuff
}
pro-gramer
  • 166
  • 1
  • 3
  • 14
cairol
  • 8,573
  • 9
  • 27
  • 25

6 Answers6

78

You need:

  • a reference so you can access the exception polymorphically
  • a const to increase performance, and tell the compiler you're not going to modify the object

The latter is not as much important as the former, but the only real reason to drop const would be to signal that you want to do changes to the exception (usually useful only if you want to rethrow it with added context into a higher level).

Kornel Kisielewicz
  • 55,802
  • 15
  • 111
  • 149
  • 1
    "tell the compiler you're not going to modify the object"—I suppose that might be useful if you're passing the object as a parameter to a function call. – Craig McQueen Nov 27 '13 at 02:52
  • 2
    what do you mean by 'access the exception polymorphically'? – mango Sep 11 '14 at 16:04
  • 5
    @mango presumably it means to be able to call a virtual function (such as `std::exception` 's `what()` function). If you catch by value then you couldn't call that function and get the original exception details. – M.M Jul 20 '15 at 21:35
  • 13
    looked at assembly produced by apple clang 7 and by gcc 5 (with optimisation O3) and I does not see any difference between const ref and non-const ref assembly. So, i guess there are no difference in optimisations for gcc and apple clang – Vasiliy Soshnikov Mar 28 '16 at 20:11
  • @Craig McQueen Actually exception **IS** an object and is passed to catch() block as if catch() is a function. By using reference to const compiler can avoid copying of exception object when it crosses scopes. – BJovke Jun 07 '17 at 20:29
  • 3
    The compiler can easily see which objects you modify and which not ([SSA](https://en.wikipedia.org/wiki/Static_single_assignment_form) and constant propagation). A better explanation is needed (or is it a myth?). – rustyx Jul 20 '17 at 20:33
  • 1
    > tell the compiler you're not going to modify the object More like tell future self or colleagues, compiler already knows :) – kwesolowski Sep 04 '20 at 20:47
  • 2
    const here (and in any reasonable-designed program) has nothing with performance! – Arthur P. Golubev Aug 24 '21 at 23:45
  • Catch by `const&` to avoid [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) of the exception. Catch-by-value creates a (sliced) copy of the original; catch by reference also creates a (sliced) copy. Only catch by const reference preserves the original exception – jwm Sep 17 '21 at 17:57
  • I have also seen libraries throwing a const object, which cannot be handled without a `const` in the catch block. – mgruber4 Jun 02 '22 at 07:46
40

There is basically no reason at all.

Exception objects live in their own memory space so you don't have to worry about catching exceptions created in temporary expressions.

All you're doing is promising that you won't modify the exception object, but since exception objects should have an immutable interface, there is really nothing practical here.

However, it might make you feel warm and cosy when you read it — that's how it is for me!

They have their own, special, thread-local stack.
Disclaimer: Boost.Exception breaks this in order to do funky stuff and add exception details, post-construction. But this is hackery!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Could you please elaborate on `Exception objects live in their own memory space` ? Do you have a good read to suggest about it ? – Richard Dally Jan 20 '16 at 13:29
  • 1
    @LeFlou: I could point you to the standard, but it'd be a bit misleading to deem that "a good read"... :P – Lightness Races in Orbit Jan 20 '16 at 23:54
  • Definitely yes, it would be interesting to learn more about this from standard point of view. I'm reading [Technical Report on C++ Performance](http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf), do you have a more relevant document ? – Richard Dally Jan 21 '16 at 10:58
  • @LeFlou: Well, it doesn't get any more authoritative than the standard itself.... – Lightness Races in Orbit Jan 21 '16 at 13:08
  • I meant another document from standard :) – Richard Dally Jan 21 '16 at 13:13
  • I'm curious to see where exactly in the standard does it state that exceptions should have an immutable interface... and *how* would having an immutable interface improve performance? – rustyx Jul 20 '17 at 20:27
  • @rustyx: The standard doesn't state it, common sense does .. and I did not claim that having an immutable interface improves performance. In fact, I myself questioned this claim on some of the other answers. – Lightness Races in Orbit May 15 '18 at 11:28
  • 2
    @RichardDally check *C++ Primer 5th*, § 18.1.1 Excpetion Object. It says *The exception object resides in space, managed by the compiler, that is guaranteed to be accessible to whatever catch is invoked. The exception object is destroyed after the exception is completely handled.* – Rick Sep 19 '18 at 04:25
  • This is a terrible answer. If you catch an exception by anything other than `const&`, the compiler creates a copy (potentially [slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) the original exception). – jwm Sep 17 '21 at 17:49
5

It tells the compiler that you won't be calling any function which modify the exception, which may help to optimize the code. Probably doesn't make much of a difference, but the cost of doing it is very small too.

Warpin
  • 6,971
  • 12
  • 51
  • 77
2

are you going to modify the exception? if not, it may as well be const. same reason you SHOULD use const anywhere else (I say SHOULD because it doesn't really make that much difference on the surface, might help compilers, and also help coders use your code properly and not do stuff they shouldn't)

exception handlers, may be platform specific, and may put exceptions in funny places because they aren't expecting them to change?

matt
  • 4,042
  • 5
  • 32
  • 50
0

To call std::exception::what() and get the original message instead of "std::exception".

This is implicit in other response but is the main use case for me, it is a confusing issue with polymorphic exceptions, and should be highlighted accordingly.

BTW in local context / same function, .what() works usually fine. I guess because of compiler optimizations.

gatopeich
  • 3,287
  • 31
  • 26
-4

For the same reason you use a const.