Те, що вам здається, потрапило в певне пекло того, хто намагається випити їх торт і з'їсти його теж.
RAII та винятки призначені для того, щоб йти рука об руку. RAII - це засіб, за допомогою якого вам не потрібно писати багато catch(...)
заяв, щоб зробити очищення. Це відбудеться автоматично, як зрозуміло. А винятки - єдиний спосіб роботи з об’єктами RAII, оскільки конструктори можуть лише домогтися успіху або кинути (або поставити об'єкт у стан помилки, але хто цього хоче?).
catch
Заява може зробити один з двох речей: обробляти помилки або виняткові обставини, або робити роботу по очищенню. Іноді це робить і те, і інше, але кожне catch
твердження існує, щоб зробити принаймні одне з них.
catch(...)
не може зробити належну обробку виключень. Ви не знаєте, що таке виняток; ви не можете отримати інформацію про виняток. У вас немає абсолютно ніякої інформації, крім того, що виняток було кинуто чимось у певному кодовому блоці. Єдине законне, що ви можете зробити в такому блоці - це зробити очищення. А це означає перекинути виняток наприкінці очищення.
Що дає RAII щодо обробки винятків, це безкоштовне очищення. Якщо все RAII інкапсульовано належним чином, то все буде належним чином очищено. Вам більше не потрібно, щоб catch
заяви чистили. У такому випадку писати catch(...)
заяву немає підстав .
Тож я погодився б, що catch(...)
це злість ... тимчасово .
Це положення є належним використанням RAII. Тому що без цього потрібно вміти робити певну очистку. Не обійти його; ви повинні вміти робити прибирання. Потрібно мати можливість переконатися, що кидання винятку залишить код у розумному стані. І catch(...)
це життєво важливий інструмент для цього.
Не можна мати одне без іншого. Ви не можете сказати, що і RAII, і catch(...)
погані. Вам потрібно хоча б одне із них; інакше ти не безпечний виняток.
Звичайно, є одне дійсне, хоча і рідкісне використання, catch(...)
яке навіть RAII не може прогнати: отримання exception_ptr
переадресації комусь іншому. Зазвичай через promise/future
чи подібний інтерфейс.
Мої колеги кажуть, що ви завжди повинні знати, які винятки потрібно кинути, і що ви завжди можете використовувати такі конструкції:
Ваш колега - ідіот (або просто жахливо необізнаний). Це повинно бути відразу очевидним через те, скільки копіювати та вставляти код він пропонує вам написати. Очищення для кожної з цих заяв на вилов буде точно однаковою . Це кошмар технічного обслуговування, не кажучи вже про читанність.
Коротше кажучи: це проблема, яку RAII створили для вирішення (не те, що вона не вирішує інших проблем).
Що мене бентежить у цьому понятті, це те, що воно, як правило, відстало від того, як більшість людей стверджує, що RAII поганий. Як правило, аргумент "RAII поганий, тому що ви повинні використовувати винятки для відмови конструктора сигналів. Але винятки не можете кидати, тому що це не безпечно, і вам доведеться мати багато catch
тверджень, щоб очистити все". Що є неполадним аргументом, тому що RAII вирішує проблему, яку створює брак RAII.
Більш ніж ймовірно, він проти RAII, оскільки він приховує деталі. Виклики деструктора не видно відразу в автоматичних змінних. Таким чином, ви отримуєте код, який викликається неявно. Деякі програмісти дуже ненавиджу це. Судячи з усього, catch
краща ідея, якщо вони думають, що мають 3 твердження, всі вони роблять те ж саме з кодом копіювання та вставки.
...
", тоді як моє питання зосереджується на "Чи слід краще ловити...
або<specific exception>
перед тим, як відкинути"