Рад, что вы опубликовали это как вопрос. :)
Я пытался сказать, что деструкторы и 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.
Другими словами, просто потому, что вы можете использовать либо для симуляции, либо это не означает, что оба являются одной и той же проблемой, или что оба являются подходящими решениями для обеих проблем.