Радий, що ви опублікували це як питання. :)
Я намагався сказати, що деструктори і finallyконцептуально різні:
- Деструктори для випуску ресурсів ( даних )
finallyпризначений для повернення абоненту ( контроль )
Розглянемо, скажімо, цей гіпотетичний псевдокод:
try {
bar();
} finally {
logfile.print("bar has exited...");
}
finallyтут вирішується повністю проблема управління, а не проблема управління ресурсами.
Не було б сенсу робити це в деструкторі з різних причин:
- Ні річ не бути «придбала» або «створив»
- Якщо не надрукувати файл журналу, це не призведе до витоку ресурсів, пошкодження даних тощо (якщо припустити, що файл журналу тут не повертається в програму в іншому місці)
- Це правомірно
logfile.printвідмовити, тоді як руйнування (концептуально) не може зазнати збою
Ось ще один приклад, цього разу, як у Javascript:
var mo_document = document, mo;
function observe(mutations) {
mo.disconnect(); // stop observing changes to prevent re-entrance
try {
/* modify stuff */
} finally {
mo.observe(mo_document); // continue observing (conceptually, this can fail)
}
}
mo = new MutationObserver(observe);
return observe();
У наведеному вище прикладі, знову ж таки, немає ресурсів для звільнення.
Насправді, finallyблок отримання внутрішніх ресурсів для досягнення своєї мети, яка потенційно може потерпіти невдачу. Отже, не має сенсу використовувати деструктор (якщо у Javascript був такий).
З іншого боку, у цьому прикладі:
b = get_data();
try {
a.write(b);
} finally {
free(b);
}
finallyзнищує ресурс, b. Це проблема даних. Проблема полягає не в чистому поверненні контролю абоненту, а в уникненні витоків ресурсів.
Відмова не є варіантом, і не повинен (концептуально) ніколи виникати.
Кожен реліз bобов'язково поєднується з придбанням, і є сенс використовувати RAII.
Іншими словами, тільки тому, що ви можете використовувати або для імітації, або це не означає, що обидві є однією і тією ж проблемою, або що обидва є відповідними рішеннями для обох проблем.