Из Википедии, бесплатной энциклопедии
  (Перенаправлено из раздела "Завершение" )
Перейти к навигации Перейти к поиску

В информатике , A финализации или финализации метод является специальным методом , который выполняет доработки , обычно какой - либо форме очистки. Финализатор выполняется во время уничтожения объекта , до освобождения объекта , и является дополнением к инициализатору , который выполняется во время создания объекта после выделения . Некоторые настоятельно не рекомендуют финализаторы из-за трудностей в правильном использовании и сложности, которую они добавляют, и вместо этого предлагаются альтернативы, в первую очередь шаблон удаления [1] - см. Проблемы с финализаторами.

Термин «финализатор» в основном используется в объектно-ориентированных и функциональных языках , использующих сборку мусора , архетипом которого является Smalltalk . Это контрастирует с « деструктором », который представляет собой метод, вызываемый для завершения в языках с детерминированным временем жизни объекта, архетипично C ++ . [2] [3] Как правило, они эксклюзивны - у языка есть либо финализаторы (при автоматическом сборке мусора), либо деструкторы (при ручном управлении памятью), но в редких случаях язык может иметь и то, и другое, как в C ++ / CLI и D , и в случае подсчета ссылок(вместо отслеживания сборки мусора) терминология меняется. В техническом использовании термин «финализатор» также может использоваться для обозначения деструкторов, так как они также выполняют финализацию, и при этом проводятся некоторые более тонкие различия - см. Терминологию . Термин «окончательный» также используется для обозначения класса, который не может быть унаследован ; это не связано.

Терминология [ править ]

Терминология «финализатор» и «финализация» по сравнению с «деструктором» и «уничтожением» варьируется между авторами и иногда неясна.

Обычно деструктор - это метод, детерминированно вызываемый при разрушении объекта, а архетип - деструкторы C ++; в то время как финализатор вызывается сборщиком мусора недетерминированно, а архетипом являются finalizeметоды Java .

Для языков, которые реализуют сборку мусора через подсчет ссылок , терминология различается: некоторые языки, такие как Objective-C и Perl, используют «деструктор», а другие языки, такие как Python, используют «финализатор» (согласно спецификации Python собирает мусор, но ссылка Реализация CPython, начиная с версии 2.0, использует комбинацию подсчета ссылок и сборки мусора). Это отражает тот факт, что подсчет ссылок приводит к полудетерминированному времени жизни объекта: для объектов, которые не являются частью цикла, объекты уничтожаются детерминированно, когда счетчик ссылок падает до нуля, но объекты, которые являются частью цикла, уничтожаются недетерминированно. , как часть отдельной формы сборки мусора.

В определенном узком техническом использовании, «конструктор» и «деструктор» являются терминами уровня языка, означающими «методы, определенные в классе», в то время как «инициализатор» и «финализатор» являются терминами уровня реализации, означающими «методы, вызываемые во время создания объекта или разрушение ". Так, например, исходная спецификация языка C # называлась «деструкторами», хотя C # собирает мусор, но спецификация Common Language Infrastructure (CLI) и реализация ее среды выполнения как Common Language Runtime (CLR ), именуемых «финализаторами». Это отражено в примечаниях комитета по языку C #, которые частично гласят: «Компилятор C # компилирует деструкторы для ...Эта терминология сбивает с толку, и поэтому в более поздних версиях спецификации C # метод уровня языка называется «финализаторами». [6]

Другой язык, который не делает этого терминологического различия, - D. Хотя классы D собираются сборщиком мусора, их функции очистки называются деструкторами. [7]

Используйте [ редактировать ]

Финализация в основном используется для очистки, освобождения памяти или других ресурсов: для освобождения памяти, выделенной с помощью ручного управления памятью ; для очистки ссылок, если используется подсчет ссылок (уменьшение количества ссылок); для высвобождения ресурсов, особенно в инициализации получения ресурсов.(RAII) идиома; или отменить регистрацию объекта. Объем финализации значительно варьируется между языками, от обширной финализации в C ++, который имеет ручное управление памятью, подсчет ссылок и детерминированное время жизни объектов; часто без финализации в Java, которая имеет недетерминированное время жизни объектов и часто реализуется с помощью сборщика мусора с трассировкой. Также возможно, что явная (определяемая пользователем) финализация будет незначительной или не будет отсутствовать, но будет значительная неявная финализация, выполняемая компилятором, интерпретатором или средой выполнения; это обычное дело в случае автоматического подсчета ссылок, как в эталонной реализации Python CPython , или в автоматическом подсчете ссылок в реализации Apple Objective-C, которые автоматически разрывают ссылки во время финализации. Финализатор может включать произвольный код; особенно сложное использование - автоматическое возвращение объекта в пул объектов .

Освобождение памяти во время завершения является обычным явлением в таких языках, как C ++, где ручное управление памятью является стандартным, но также происходит в управляемых языках, когда память выделяется вне управляемой кучи (вне языка); в Java это происходит с собственным интерфейсом Java (JNI) и ByteBufferобъектами в новом вводе- выводе (NIO). Это последнее может вызвать проблемы из-за того, что сборщик мусора не может отслеживать эти внешние ресурсы, поэтому они не будут собираться достаточно агрессивно и могут вызвать ошибки нехватки памяти из-за исчерпания неуправляемой памяти - этого можно избежать, обработав собственные память в качестве ресурса и с использованием шаблона удаления , как описано ниже.

Финализаторы, как правило, гораздо менее необходимы и используются гораздо реже, чем деструкторы. Они гораздо менее необходимы, потому что сборка мусора автоматизирует управление памятью , и гораздо реже используются, потому что они обычно не выполняются детерминированно - они не могут быть вызваны своевременно или даже вообще, а среда выполнения не может быть предсказана - и, следовательно, любые очистка, которая должна выполняться детерминированным образом, должна вместо этого выполняться каким-либо другим методом, чаще всего вручную с помощью шаблона удаления . Примечательно, что и Java, и Python не гарантируют, что финализаторы когда-либо будут вызваны, и поэтому на них нельзя полагаться при очистке.

Из-за отсутствия контроля программиста над их выполнением обычно рекомендуется избегать финализаторов для любых, кроме самых тривиальных, операций. В частности, операции, часто выполняемые в деструкторах, обычно не подходят для финализаторов. Распространенным анти-шаблоном является запись финализаторов, как если бы они были деструкторами, что одновременно не нужно и неэффективно из-за различий между финализаторами и деструкторами. Это особенно распространено среди программистов C ++ , поскольку деструкторы широко используются в идиоматическом C ++, следуя идиоме Resource Acquisition Is Initialization (RAII).

Синтаксис [ править ]

Языки программирования, использующие финализаторы, включают C ++ / CLI , C # , Clean , Go , Java и Python . Синтаксис значительно различается в зависимости от языка.

В Java финализатор - это вызываемый метод finalize, который переопределяет Object.finalizeметод. [8]

В Python финализатор - это метод, называемый __del__.

В Perl финализатор - это метод, называемый DESTROY.

В C # финализатор (называемый «деструктором» в более ранних версиях стандарта) - это метод, имя которого представляет собой имя класса с ~префиксом, например ~Foo- это тот же синтаксис, что и деструктор C ++ , и эти методы изначально назывались «деструкторами». "по аналогии с C ++, несмотря на другое поведение, но были переименованы в" финализаторы "из-за возникшей путаницы. [6]

В C ++ / CLI, который имеет как деструкторы, так и финализаторы, деструктор - это метод, имя которого представляет собой имя класса с ~префиксом, как в ~Foo(как в C #), а финализатор - это метод, имя которого представляет собой имя класса с !префиксом, как в !Foo.

В Go финализаторы применяются к одному указателю путем вызова runtime.SetFinalizerфункции в стандартной библиотеке. [9]

Реализация [ править ]

Финализатор вызывается, когда объект собирается сборщиком мусора - после того, как объект стал мусором (недоступен), но до того, как его память будет освобождена. Финализация происходит недетерминированно, по усмотрению сборщика мусора и может никогда не произойти. Это контрастирует с деструкторами, которые вызываются детерминированно, как только объект больше не используется, и вызываются всегда, за исключением случая неконтролируемого завершения программы. Финализаторы чаще всего являются методами экземпляра из-за необходимости выполнять операции с объектами.

Сборщик мусора также должен учитывать возможность воскрешения объекта. Чаще всего это делается путем сначала выполнения финализаторов, затем проверки, были ли воскрешены какие-либо объекты, и, если да, отмены их уничтожения. Эта дополнительная проверка потенциально дорогостоящая - простая реализация повторно проверяет весь мусор, если хотя бы один объект имеет финализатор - и, таким образом, замедляет и усложняет сборку мусора. По этой причине объекты с финализаторами могут собираться реже, чем объекты без финализаторов (только в определенных циклах), что усугубляет проблемы, вызванные расчетом на быстрое завершение, например утечки ресурсов.

Если объект воскресает, возникает дополнительный вопрос, будет ли его финализатор вызван снова, когда он будет уничтожен в следующий раз - в отличие от деструкторов, финализаторы потенциально вызываются несколько раз. Если для воскрешенных объектов вызываются финализаторы, объекты могут многократно воскрешать себя и быть неразрушаемыми; это происходит в реализации Python CPython до Python 3.4 и в языках CLR, таких как C #. Чтобы избежать этого, на многих языках, включая Java, Objective-C (по крайней мере, в последних реализациях Apple) и Python из Python 3.4, объекты финализируются не чаще одного раза, что требует отслеживания, был ли объект еще завершен.

В других случаях, особенно в языках CLR, таких как C #, финализация отслеживается отдельно от самих объектов, и объекты могут повторно регистрироваться или отменяться для завершения.

Проблемы [ править ]

Финализаторы могут вызвать значительное количество проблем, поэтому ряд властей настоятельно не одобряют их. [10] [11] Эти проблемы включают: [10]

  • Финализаторы не могут быть вызваны своевременно или вообще не могут быть вызваны, поэтому на них нельзя полагаться в отношении сохранения состояния, высвобождения ограниченных ресурсов или выполнения каких-либо других важных действий.
  • Финализаторы могут привести к воскрешению объекта , что часто является ошибкой программирования и сама вероятность которого значительно замедляет и усложняет сборку мусора.
  • Финализаторы запускаются на основе сборки мусора, которая обычно основана на управляемой нехватке памяти - они не запускаются в случае нехватки других ресурсов и, следовательно, не подходят для управления другими дефицитными ресурсами.
  • Финализаторы не выполняются в указанном порядке и не могут полагаться на инварианты класса (поскольку они могут ссылаться на другие объекты, которые уже были финализированы).
  • Медленные финализаторы могут задерживать другие финализаторы.
  • Исключения в финализаторах обычно не могут быть обработаны, потому что финализатор запускается в неопределенной среде и может либо игнорироваться, либо вызывать неконтролируемое завершение программы.
  • Финализаторы могут ссылаться на живые объекты и случайно финализировать их, нарушая инварианты программы.
  • Финализаторы могут вызвать проблему синхронизации, даже в других последовательных (однопоточных) программах, поскольку финализация может выполняться одновременно (конкретно, в одном или нескольких отдельных потоках). [12]
  • Финализаторы могут вызвать взаимоблокировку, если используются механизмы синхронизации, такие как блокировки, из-за того, что они не выполняются в указанном порядке и, возможно, выполняются одновременно.
  • Финализаторы, которые запускаются во время завершения программы, не могут полагаться на обычную среду выполнения и, следовательно, могут выйти из строя из-за неправильных предположений - по этой причине финализаторы часто не запускаются во время завершения.

Кроме того, финализаторы могут не работать из-за того, что объекты остаются доступными после того, как ожидается, что они будут мусором, либо из-за ошибок программирования, либо из-за неожиданной достижимости. Например, когда Python перехватывает исключение (или исключение не перехватывается в интерактивном режиме), он сохраняет ссылку на фрейм стека, в котором возникло исключение, что сохраняет объекты, на которые ссылается этот фрейм стека, живыми.

Финализаторы в суперклассе также могут замедлить сборку мусора в подклассе, поскольку финализатор потенциально может ссылаться на поля в подклассе, и, таким образом, поле не может быть собрано сборщиком мусора до следующего цикла после запуска финализатора. [10] Этого можно избежать, если использовать композицию вместо наследования .

Управление ресурсами [ править ]

Распространенным анти-шаблоном является использование финализаторов для освобождения ресурсов по аналогии с идиомой Resource Acquisition Is Initialization (RAII) в C ++: получить ресурс в инициализаторе (конструкторе) и освободить его в финализаторе (деструкторе). Это не работает по ряду причин. По сути, финализаторы могут никогда не вызываться, и даже если они вызваны, они могут не вызываться своевременно - таким образом, использование финализаторов для освобождения ресурсов обычно вызывает утечки ресурсов.. Кроме того, финализаторы не вызываются в установленном порядке, тогда как ресурсы часто необходимо освобождать в определенном порядке, часто в порядке, обратном тому, в котором они были получены. Кроме того, поскольку финализаторы вызываются по усмотрению сборщика мусора, они часто будут вызываться только при нехватке управляемой памяти (когда доступно мало управляемой памяти), независимо от нагрузки на ресурсы - если скудные ресурсы удерживаются мусором, но их много доступной управляемой памяти, сборка мусора может не произойти, поэтому эти ресурсы не будут восстановлены.

Таким образом, вместо использования финализаторов для автоматического управления ресурсами в языках со сборкой мусора необходимо вручную управлять ресурсами, как правило, с использованием шаблона удаления . В этом случае ресурсы все еще могут быть получены в инициализаторе, который вызывается явно при создании экземпляра объекта, но освобождается в методе удаления. Метод dispose может вызываться явно или неявно языковыми конструкциями, такими как C # using, Java try-with-resources или Python with.

Однако в некоторых случаях для освобождения ресурсов используются как шаблон удаления, так и финализаторы. Это в первую очередь встречается в языках CLR, таких как C #, где финализация используется в качестве резервной копии для удаления: когда ресурс приобретается, получающий объект ставится в очередь для завершения, так что ресурс освобождается при уничтожении объекта, даже если ресурс не выпущен путем ручной утилизации.

Детерминированное и недетерминированное время жизни объекта [ править ]

В языках с детерминированным временем жизни объекта, особенно в C ++, управление ресурсами часто осуществляется путем привязки времени жизни владения ресурсом к времени жизни объекта, получения ресурсов во время инициализации и освобождения их во время финализации; это известно как инициализация получения ресурсов (RAII). Это гарантирует, что владение ресурсами является инвариантом класса , и что ресурсы высвобождаются сразу после уничтожения объекта.

Однако в языках с недетерминированным временем жизни объектов - которые включают все основные языки со сборкой мусора, такие как C #, Java и Python - это не работает, потому что финализация может быть несвоевременной или может не произойти вообще, и, следовательно, ресурсы могут не выпускаться в течение длительного времени или вообще не выпускаться, вызывая утечку ресурсов . Вместо этого в этих языках ресурсы обычно управляются вручную с помощью шаблона удаления : ресурсы могут быть получены во время инициализации, но освобождаются путем вызова disposeметода. Тем не менее, использование финализации для освобождения ресурсов на этих языках является распространенным анти-шаблоном , и забвение вызова disposeвсе равно приведет к утечке ресурсов.

В некоторых случаях оба метода комбинируются, используя явный метод удаления, но также освобождая все еще удерживаемые ресурсы во время финализации в качестве резервной копии. Это обычно встречается в C # и реализуется путем регистрации объекта для завершения при каждом получении ресурса и подавления завершения при освобождении ресурса.

Воскрешение объекта [ править ]

Если определенные пользователем финализаторы разрешены, финализация может вызвать воскрешение объекта , поскольку финализаторы могут запускать произвольный код, который может создавать ссылки из живых объектов на уничтожаемые объекты. Для языков без сборки мусора это серьезная ошибка, вызывающая висячие ссылки и нарушения безопасности памяти ; для языков со сборкой мусора это предотвращается сборщиком мусора, чаще всего путем добавления еще одного шага к сборке мусора (после запуска всех указанных пользователем финализаторов проверяйте воскрешение), что усложняет и замедляет сборку мусора.

Кроме того, воскрешение объекта означает, что объект не может быть уничтожен, а в патологических случаях объект всегда может воскресить себя во время завершения, сделав себя неразрушимым. Чтобы предотвратить это, некоторые языки, такие как Java и Python (начиная с Python 3.4), завершают объекты только один раз и не завершают завершение воскрешенных объектов. Конкретно это делается путем отслеживания, был ли объект завершен для каждого объекта отдельно. Objective-C также отслеживает финализацию (по крайней мере, в последних версиях Apple) по аналогичным причинам, рассматривая воскрешение как ошибку.

Другой подход используется в .NET Framework , особенно в C # и Visual Basic .NET , где финализация отслеживается по «очереди», а не по объекту. В этом случае, если предоставляется указанный пользователем финализатор, по умолчанию объект завершается только один раз (он ставится в очередь для завершения при создании и удаляется из очереди после завершения), но это можно изменить, вызвав GCмодуль. Завершение можно предотвратить путем вызова GC.SuppressFinalize, который выводит объект из очереди, или повторно активировать вызовом GC.ReRegisterForFinalize, который ставит объект в очередь. Они особенно используются при использовании финализации для управления ресурсами в качестве дополнения к шаблону удаления или при реализации пула объектов .

В отличие от инициализации [ править ]

Финализация формально дополняет инициализацию - инициализация происходит в начале жизненного цикла, финализация - в конце, но на практике существенно отличается. И переменные, и объекты инициализируются, в первую очередь, для присвоения значений, но, как правило, завершаются только объекты, и, как правило, нет необходимости очищать значения - операционная система может просто освободить и освободить память.

Помимо присвоения начальных значений, инициализация в основном используется для получения ресурсов или для регистрации объекта в какой-либо службе (например, обработчик событий). Эти действия имеют симметричные действия по освобождению или отмене регистрации, и они могут симметрично обрабатываться в финализаторе, что выполняется в RAII. Однако во многих языках, особенно в языках со сборкой мусора, время жизни объекта асимметрично: создание объекта происходит детерминированно в некоторой явной точке кода, но уничтожение объекта происходит недетерминированно, в некоторой неопределенной среде, по усмотрению сборщика мусора. Эта асимметрия означает, что финализация не может эффективно использоваться в качестве дополнения к инициализации, потому что она не происходит своевременно, в указанном порядке или в указанной среде. Симметрия частично восстанавливается также путем размещения объекта в явной точке, но в этом случае удаление и разрушение не происходят в одной и той же точке, и объект может находиться в "инварианты класса и усложняет использование.

Переменные обычно инициализируются в начале своего жизненного цикла, но не завершаются в конце своего времени существования - хотя, если переменная имеет объект в качестве значения, объект может быть завершен. В некоторых случаях переменные также финализируются: расширения GCC позволяют финализировать переменные.

Связь с finally[ править ]

Как отражено в названии, «завершение» и finallyконструкция выполняют схожие цели: выполнение некоторого заключительного действия, обычно очистки, после того, как что-то еще было завершено. Они различаются тем, когда они возникают - finallyпредложение выполняется, когда выполнение программы покидает тело связанного tryпредложения - это происходит во время раскрутки стека, и, таким образом, существует стек ожидающих finallyпредложений по порядку - в то время как завершение происходит при уничтожении объекта, что происходит в зависимости от метода управления памятью, и, как правило, существует просто набор объектов, ожидающих завершения - часто в куче - что не обязательно должно происходить в каком-либо определенном порядке.

Однако в некоторых случаях они совпадают. В C ++ разрушение объекта является детерминированным, и поведение finallyпредложения может быть произведено с помощью локальной переменной с объектом в качестве значения, чья область видимости является блоком, соответствующим телу tryпредложения - объект завершается (уничтожается), когда выполнение выходит из этой области точно так же, как если бы было finallyпредложение. По этой причине в C ++ нет finallyконструкции - разница в том, что финализация определяется в определении класса как метод деструктора, а не на месте вызова в finallyпредложении.

И наоборот, в случае finallyпредложения в сопрограмме , как в генераторе Python, сопрограмма может никогда не завершиться - только когда-либо уступить - и, таким образом, при обычном выполнении finallyпредложение никогда не выполняется. Если интерпретировать экземпляры сопрограммы как объекты, то finallyпредложение можно рассматривать как финализатор объекта и, таким образом, может выполняться, когда экземпляр собирает мусор. В терминологии Python определение сопрограммы - это функция генератора , а ее экземпляр - итератор генератора , и, таким образом, finallyпредложение в функции генератора становится финализатором в итераторах генератора, созданных из этой функции.

История [ править ]

Идея завершения как отдельного шага в разрушении объекта восходит к Монтгомери (1994) , [13] по аналогии с более ранним различием инициализации при построении объекта у Мартина и Оделла (1992) . [14] В литературе до этого момента для этого процесса использовалось «уничтожение», не различая финализации и освобождения, а в языках программирования, относящихся к этому периоду, таких как C ++ и Perl, использовался термин «уничтожение». Термины «завершение» и «завершение» также используются во влиятельной книге « Шаблоны проектирования» (1994). [a] [15] Введение Java в 1995 г. содержалоfinalize методы, которые популяризировали этот термин и связали его со сборкой мусора, и языки с этого момента обычно делают это различие и используют термин «завершение», особенно в контексте сборки мусора.


См. Также [ править ]

  • Сборка мусора , в частности раздел о детерминизме
  • Время жизни объекта
  • Процесс инициализации и соответствующий шаблон инициализатора

Заметки [ править ]

  1. Опубликовано в 1994 г. с авторским правом 1995 г.

Ссылки [ править ]

  1. ^ Джаггер, Perry & Sestoft 2007 , стр. 542 , «В C ++ деструктор вызывается определенным образом, тогда как в C # финализатор - нет. Чтобы получить определенное поведение из C #, следует использоватьDispose.
  2. Перейти ↑ Boehm, Hans-J. (2002). Деструкторы, финализаторы и синхронизация . ПОПЛ.
  3. ^ Джаггер, Perry & Sestoft 2007 , стр. 542 , деструкторы C ++ по сравнению с финализаторами C # Деструкторы C ++ являются детерминированными в том смысле, что они запускаются в известные моменты времени, в известном порядке и из известного потока. Таким образом, они семантически сильно отличаются от финализаторов C #, которые запускаются в неизвестные моменты времени, в неизвестном порядке, из неизвестного потока и по усмотрению сборщика мусора.
  4. ^ В полном объеме: «Мы собираемся использовать термин« деструктор »для члена, который выполняется, когда экземпляр восстанавливается. Классы могут иметь деструкторы; структуры не могут. В отличие от C ++, деструктор не может быть вызван явно. Разрушение не -детерминированный - вы не можете достоверно знать, когда будет выполняться деструктор, за исключением того, чтобы сказать, что он выполняется в какой-то момент после того, как все ссылки на объект были освобождены. Деструкторы в цепочке наследования вызываются по порядку, от большинства потомков до наименее потомок. Для производного класса нет необходимости (и нет возможности) явно вызывать базовый деструктор. Компилятор C # компилирует деструкторы в соответствующее представление CLR. Для этой версии это, вероятно, означает финализатор экземпляра, который выделяется в метаданных. CLR может предоставлять статические финализаторы в будущем; мы не видим никаких препятствий для использования в C # статических финализаторов », 12 мая 1999 г.
  5. ^ В чем разница между деструктором и финализатором? , Эрик Липперт, Блог Эрика Липперта: сказочные приключения в программировании, 21 января 2010 г.
  6. ^ a b Джаггер, Perry & Sestoft 2007 , стр. 542 , «В предыдущей версии этого стандарта то, что теперь называется« финализатор », называлось« деструктором ». Опыт показал, что термин« деструктор »вызывал путаницу и часто приводил к неверным ожиданиям, особенно для программистов, знающих C ++. В C ++ деструктор вызывается определенным образом, тогда как в C # финализатор - нет. Чтобы получить определенное поведение из C #, следует использовать Dispose."
  7. ^ Деструкторы классов Деструкторы классов в D
  8. ^ java.lang, Объект класса: завершить
  9. ^ https://golang.org/pkg/runtime/#SetFinalizer
  10. ^ a b c « MET12-J. Не использовать финализаторы », Дхрув Мохиндра, Стандарт безопасного кодирования CERT Oracle для Java , 05. Методы (MET)
  11. ^ object .__ del __ (self) , Справочник по языку Python , 3. Модель данных : «...__del__()методы должны выполнять абсолютный минимум, необходимый для поддержания внешних инвариантов».
  12. ^ Ханс-Дж. Бём, Завершение, потоки и модель памяти на основе технологии Java ™, Конференция JavaOne, 2005.
  13. Перейти ↑ Montgomery 1994 , p. 120 : «Как и в случае создания экземпляров объекта, при проектировании завершения объекта может быть полезна реализация двух операций для каждого класса-операции завершения и завершения. Операция завершения разрывает ассоциации с другими объектами, обеспечивая целостность структуры данных».
  14. Перейти ↑ Montgomery 1994 , p. 119 , «Рассмотрите реализацию создания экземпляра класса какоперации создания и инициализации , как было предложено Мартином и Оделлом. Первый выделяет память для новых объектов, а второйсоздаетобъект в соответствии со спецификациями и ограничениями».
  15. ^ «Каждый новый класс имеет фиксированные накладные расходы на реализацию (инициализация, завершение и т. Д.).», « Деструктор. В C ++ - операция, которая автоматически вызывается для завершения объекта, который будет удален».

Дальнейшее чтение [ править ]

  • Джаггер, Джон; Перри, Найджел; Сестофт, Питер (2007). Аннотированный стандарт C # . Морган Кауфманн. ISBN 978-0-12-372511-0.
  • Мартин, Джеймс; Оделл, Джеймс Дж. (1992). Объектно-ориентированный анализ и дизайн . Прентис-Холл. ISBN 978-0-13-630245-2.
  • Монтгомери, Стивен (1994). Объектно-ориентированная информационная инженерия: анализ, проектирование и реализация . Академическая пресса. ISBN 978-0-12-505040-1.

Внешние ссылки [ править ]

  • « Завершить вместо правильного деструктора », WikiWikiWeb - сравнение финализаторов Java с деструкторами C ++
  • Пол Крилл, « Oracle рекомендует отказаться от финализатора объектов Java », JavaWorld, 29 марта 2017 г.