2

I read the "Programming: Principles and Practice using C++" book (Bjarne Stroustrup). Sometimes the author writes:

catch (runtime_error e)

but sometimes he writes:

catch (runtime_error& e)

As I know, the first variant creates the copy of source, but the second uses the link. Or am I mistaken? Is this not important for the "catch" in this case?

psibar
  • 1,910
  • 1
  • 12
  • 17
Andrey Bushman
  • 11,712
  • 17
  • 87
  • 182
  • The second catches by reference. You need to understand what references are first, then read the article I linked as a duplicate. – pmr May 15 '13 at 11:17

4 Answers4

9

I would have expected that most of the time, he would use:

catch ( runtime_error const& e )

The difference between catch by value and catch by reference is exactly the same as pass by value and pass by reference for a function parameter. The most important difference is that when catching by reference, the dynamic type can be a derived type, by value will result in slicing (because of the copy).

Also, if you catch by non-const reference, and modify the exception object, then rethrow, it is the modified object which will propagate.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
4

In order to avoid unnecessary copies AND slicing, you should always catch the exception by reference. Especially in the cases, when you plan to re-throw; it.

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
3

Catch by value

catch (runtime_error e)

versus catch by reference

catch (runtime_error& e)

You'd use the later when you have (usualy polymorphic) exception class hierarchy and you want to catch exceptions of all the derived types in a single catch clause.

For example, all the exception classes from the standard library derive from std::exception, so you can do something like this:

try {
    int i;
    std::cin >> i;
    switch (i) {
        case 1:  throw std::range_error();
        case 2:  throw std::overflow_error();
        case 3:  throw std::undefflow_error();
        default: throw std::logic_error();
    }
} catch (std::exception& e) {
    // handle all the exceptions the same way,
    // but print a diagnostic message polimorphicaly
    std::cout << "I caught: " << e.what() << '\n';
}

If, instead by reference, you'd catch by value, you'd always catch a std::exception, sliced off of the derived part of the object.

jrok
  • 54,456
  • 9
  • 109
  • 141
1

You should always catch by reference; there is absolutely no reason to catch by value.

Don't trust everything that is written. ;-)

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • But it wroted by Bjarne Stroustrup. It is unlikely he is mistaken. – Andrey Bushman May 15 '13 at 11:17
  • 3
    Why? I catch by value from time to time. If you're catching `int`, for example, I can't see any reason to use the reference. – James Kanze May 15 '13 at 11:17
  • @JamesKanze: One, *throwing* `int` is a bit weird, isn't it? Two, even in this case, catching by reference doesn't *hurt*, while the reverse is not true. (I.e., catching by value has disadvantages, catching by reference has not; that's what I said.) In the quick & short environment of a Q&A page, I prefer giving simple rules that cannot shoot you in the foot, and leave the detailed explanations for break time in the coffee room. ;-) – DevSolar May 15 '13 at 11:20
  • 2
    @DevSolar Throwing an `int` is a good technique for exiting a program cleanly, provided `main` is aware of the convention. (The `int` is the return code.) And I'd argue that you should use the same conventions in `catch` as you use for function arguments. – James Kanze May 15 '13 at 11:23
  • 2
    @DevSolar: I wouldn't throw an `int` (since there's no indication in the handler what it means); but throwing a sensibly-named enumeration, or a structure containing one or two simple types, seems quite reasonable to me, and such things are probably better caught by value. Simple guidelines are indeed helpful; oversimplifications like "absolutely no reason" are less so. – Mike Seymour May 15 '13 at 11:31
  • The good technique for ending a program with a given return code would be `exit()` IMHO. And personally, I consider "exception" to imply "subclass of `std::exception`". Throwing `int`, enumerations (however sensibly named) or some structures hinders me to `catch ( std::exception const & e )` and forces me to `catch ( ... )`, and I wouldn't be happy with code that forces me to do that. – DevSolar May 15 '13 at 12:22
  • @Bush: Virtually every author was mistaken from time to time. Stroustrup, Kernighan & Ritchie, Guido van Rossum, Larry Wall - all of them have written less-than-optimal code at some point of their writings. The list of errata published by Stroustrup himself is [here](http://www.stroustrup.com/Programming/errata.html). Note that what you are referring to is not, in the form shown, an error, but merely a question of style. – DevSolar May 15 '13 at 12:32
  • @DevSolar: Indeed, if the exception might leave a "public" function then it should always be a subtype of `std::exception`; it's a pain to have to handle anything else. But when implementing a sufficiently complex function, calling various private functions, it's quite reasonable (in my view) to use locally defined types to represent conditions that can be handled locally. In fact, you might prefer that since you can guarantee that anything you can't handle locally (signaled with `std::exception`) won't be caught locally. But that's just me; others have more religious views on the subject. – Mike Seymour May 15 '13 at 13:23