Навіщо ловити виняток як посилання на const?


84

Я багато разів чув і читав, що краще вловлювати виняток як посилання на const, а не як посилання. Чому це:

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

краще ніж:

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

Відповіді:


67

Тобі потрібно:

  • посилання, щоб ви могли поліморфно отримати доступ до винятку
  • const для підвищення продуктивності та скажіть компілятору, що ви не збираєтеся модифікувати об'єкт

Останнє не настільки важливо, як перше, але єдиною реальною причиною відмови від const буде сигнал про те, що ви хочете внести зміни у виняток (зазвичай корисно, лише якщо ви хочете відновити його з доданим контекстом на більш високий рівень) .


1
"скажи компілятору, що ти не збираєшся модифікувати об'єкт" - я вважаю, що це може бути корисно, якщо ви передаєте об'єкт як параметр у виклик функції.
Крейг Маккуїн,

1
що ви маєте на увазі під словом «доступ до винятку поліморфно»?
манго

3
@mango, мабуть, це означає мати можливість викликати віртуальну функцію (наприклад, функцію std::exception' what()). Якщо ви ловите за значенням, ви не можете викликати цю функцію та отримати оригінальні деталі винятків.
М.М.

11
дивився на збірку, вироблену apple clang 7 та gcc 5 (з оптимізацією O3), і я не бачу різниці між збіркою const ref та non-const ref. Отже, я думаю, немає різниці в оптимізації для gcc та apple clang
Василь Сошников

2
Компілятор може легко побачити, які об'єкти ви модифікуєте, а які ні ( SSA та постійне поширення). Потрібне краще пояснення (чи це міф?).
rustyx

31

Причин узагалі немає.

Об’єкти винятків живуть у власному просторі пам’яті †, тому вам не доведеться турбуватися про те, щоб вловити винятки, створені у тимчасових виразах.

Все, що ви робите, - це обіцянка, що ви не будете модифікувати об’єкт виключення, але оскільки об’єкти виключення повинні мати незмінний інтерфейс , то насправді тут немає нічого практичного.

Тим не менш, це може змусити вас почуватись тепло і затишно, коли ви читаєте його - ось як це для мене!

Вони мають свій власний, спеціальний, локальний стек.
Застереження: Boost.Exception порушує це, щоб робити фанкі речі та додавати деталі винятків, після побудови. Але це хакерство!


Не могли б Ви докладніше розповісти Exception objects live in their own memory space? Чи маєте ви хороше читання, щоб запропонувати про це?
Річард Даллі,

@LeFlou: Я міг би вказати вам стандарт, але було б трохи оманливим вважати, що "добре читається" ...: P
Гонки легкості на орбіті

Безумовно, так, було б цікаво дізнатись більше про це зі стандартної точки зору. Я читаю Технічний звіт про продуктивність C ++ , чи є у вас більш відповідний документ?
Річард Даллі,

@LeFlou: Ну, це не стає більш авторитетним, ніж сам стандарт ....
Гонки легкості на орбіті

1
@RichardDally перевірити C ++ Primer 5th , § 18.1.1 Об'єкт очікування. У ньому сказано, що об’єкт виключення знаходиться у просторі, керованому компілятором, який гарантовано буде доступним для будь-якого викликаного лову. Об'єкт виключення знищується після повної обробки виключення.
Рік

5

Він повідомляє компілятору, що ви не будете викликати жодної функції, яка модифікує виняток, що може допомогти оптимізувати код. Можливо, великої різниці немає, але і вартість цього теж дуже мала.


2

ви збираєтеся змінити виняток? якщо ні, це також може бути const. з тієї самої причини, чому ви ПОВИННІ використовувати const де-небудь ще (я кажу СЛІД, оскільки це насправді не так сильно впливає на поверхню, може допомогти компіляторам, а також допомогти кодерам правильно використовувати ваш код і не робити речі, які вони не повинні)

обробники винятків, можуть бути специфічними для певної платформи і можуть розміщувати винятки у забавних місцях, оскільки вони не очікують від них змін?


-1

З тієї ж причини ви використовуєте const.


І з тієї ж причини, чому і віддавати перевагу посиланням над покажчиками :-)
Димитрі С.

12
Простий і простий, але насправді не відповідь.
Всезнайкий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.