Давайте начнем с того, что постулируем, что память (в десятки, сотни или даже тысячи раз) более распространена, чем все другие ресурсы вместе взятые. Каждая переменная, объект, член объекта нуждается в некоторой памяти, выделенной для него и освобожденной позже. Для каждого файла, который вы открываете, вы создаете от десятков до миллионов объектов для хранения данных, извлеченных из файла. Каждый поток TCP идет вместе с неограниченным количеством временных строк байтов, созданных для записи в поток. Мы здесь на одной странице? Отлично.
Чтобы RAII работал (даже если у вас есть готовые умные указатели для каждого варианта использования под солнцем), вам необходимо получить право собственности . Вам нужно проанализировать, кому должен принадлежать тот или иной объект, а кому нет, и когда право собственности должно быть передано от А к Б. Конечно, вы можете использовать общее владение всем , но тогда вы будете эмулировать GC с помощью интеллектуальных указателей. В этот момент становится намного проще и быстрее встроить GC в язык.
Сборка мусора освобождает вас от этой заботы о наиболее часто используемом ресурсе - памяти. Конечно, вам все равно нужно принять такое же решение для других ресурсов, но они гораздо реже (см. Выше), а сложное (например, совместное) владение тоже менее распространено. Умственная нагрузка значительно снижается.
Теперь вы назвали некоторые недостатки создания мусора для всех значений. Тем не менее, интегрировать и RA-безопасные GC, и типы значений с RAII в один язык чрезвычайно сложно, поэтому, возможно, лучше перенести эти компромиссы другими способами?
Потеря детерминизма на практике оказывается не такой уж и плохой, потому что она влияет только на время жизни детерминированного объекта . Как описано в следующем параграфе, большинство ресурсов (кроме памяти, которая является обильной и может быть переработана довольно лениво) не связаны с временем жизни объекта в этих языках. Есть несколько других вариантов использования, но они редки в моем опыте.
Ваш второй пункт, ручное управление ресурсами, в настоящее время решается с помощью оператора, который выполняет очистку на основе области действия, но не связывает эту очистку с временем жизни объекта (следовательно, не взаимодействует с ГХ и безопасностью памяти). Это using
в C #, with
в Python, try
-with-resources в последних версиях Java.