Завжди, коли використовується термін RAII, люди насправді говорять про деконструкцію замість ініціалізації. Я думаю, що я розумію, що це може означати, але я не зовсім впевнений. Також: чи є С ++ єдиною мовою RAII? Що з Java або C # /. NET?
Завжди, коли використовується термін RAII, люди насправді говорять про деконструкцію замість ініціалізації. Я думаю, що я розумію, що це може означати, але я не зовсім впевнений. Також: чи є С ++ єдиною мовою RAII? Що з Java або C # /. NET?
Відповіді:
Придбання ресурсів - це ініціалізація означає, що об’єкти повинні доглядати за собою як повний пакет, а не очікувати, що інший код вкаже на примірник "ей, до речі, ви збираєтеся очиститись незабаром - будь ласка, приберіть зараз". Зазвичай це означає, що в деструкторі є щось значиме. Це також означає, що ви пишете клас спеціально для управління ресурсами, знаючи, що за певних важко передбачуваних обставин, як, наприклад, викидів винятків, ви можете розраховувати на виконання деструкторів.
Скажімо, ви хочете написати якийсь код, де ви збираєтеся змінити курсор Windows на очікуючий (пісочний годинник, пончик непрацюючого тощо), зробіть свої речі, а потім змініть його назад. І скажіть також, що "робити свої речі" може бути винятком. Таким способом RAII було б зробити клас, у якого ctor встановив курсор на очікування, чий один "реальний" метод зробив все, що ви хотіли, і чий dtor повернув курсор назад. Ресурси (в даному випадку стан курсору) прив’язані до області об’єкта. При придбанні ресурсу ви ініціалізуєте об'єкт. Ви можете розраховувати на те, що об’єкт буде знищений, якщо будуть викинуті винятки, а це означає, що ви можете розраховувати на очищення ресурсу.
Використання RAII добре означає, що вам не потрібно finally. Звичайно, він покладається на детерміновані руйнування, яких у Java не може бути. Ви можете отримати детерміновану деструкцію в C # і VB.NET за допомогою using.
RAII частково полягає у вирішенні питання про те, коли об’єкт несе відповідальність за власне очищення - правило полягає в тому, що об'єкт несе відповідальність, якщо і коли завершиться його ініціалізація конструктора. Симетрія ініціалізації та очищення, конструктор і деструктор, означає, що вони мають тісні зв’язки один з одним.
Одним із пунктів RAII є забезпечення безпеки виключень - що програма залишається самопослідовною, коли викидаються винятки. На перший погляд це тривіально - коли виняток змушує вийти з області застосування, локальні змінні в цій області потребують знищення.
Але що станеться, якщо викид виключення відбувається в конструкторі?
Ну, об’єкт не повністю побудований, тому його не можна безпечно знищити. Конструктор повинен мати спробні блоки, щоб забезпечити виконання будь-яких необхідних очищень, перш ніж виняток буде запропоновано. Після того, як виняток подає заявку за межі області, де був побудований об'єкт, виклику деструктора не буде, тому що об'єкт не був побудований в першу чергу.
Розглянемо, зокрема, конструктори даних членів усередині об'єкта, що руйнується. Якщо хтось із них кидає виняток, ваш основний код конструктора взагалі не працюватиме, але матиме якийсь код, який утворює неявну частину цього конструктора. Будь-які члени, які були успішно побудовані, будуть автоматично знищені. Будь-які члени, які не були побудовані (включаючи того, хто кинув виняток), не є.
Таким чином, RAII - це політика, яка забезпечує те, що все, що буде повністю сконструйоване, буде своєчасно знищено, особливо за наявності викидів винятків, і що будь-який об’єкт або повністю побудований, або його немає (немає половини- побудовані об’єкти, які ви не можете знати, як безпечно очистити). Ресурси, які виділяються, також звільняються. І багато роботи автоматизовано, тому програмісту не доведеться надто турбуватися про це.