2010-02-01 2 views
3

Как нет сбора мусора в Delphi, где именно вы выгружаете переменные?Где должен класс освобождать свои частные переменные?

Скажем, у меня есть тип с набором частных варов. Достаточно ли иметь метод Destroy, который сделает это? Нужно ли мне явно вызвать этот метод destroy в моих потребляющих классах?

ответ

10

Лучший способ организовать разрушение в дельфи - это всегда думать о том, «кто создаст данные вары».

Если вы также освобождаете их в этом контексте (для вас частные методы уничтожения класса) гораздо менее вероятно, что вы столкнетесь с утечками памяти.

На самом деле деструктор класса, как правило, не вызывается через

myInstance.Destroy(); 

вместо типичный способ сделать это с помощью

FreeAndNil(myInstance); 

или

myInstance.Free(); 

Как Дельфи будет обрабатывать вызов метода деструктора по порядку

+9

+1, если вы будете следовать «который создает, разрушает», то вы уже на 98% там. –

+0

Но как далеко вы это делаете. Если, например, моя форма разрушает мой модельный класс, должен ли мой класс модели освобождать все свои собственные переменные? Мой нынешний работодатель говорит мне, что в моей форме FormDestroy() достаточно: fTheInstance.Destroy; Единственный XP, с которым я столкнулся с не-gb-сборником, был Cobol и Oberon, и мой инстинкт подсказывает мне, что строки недостаточно. –

+0

об уничтожении, взятом из «Delphi в двух словах»: http://oreilly.com/catalog /delphi/chapter/ch02.html ... При освобождении объекта вы должны вызвать метод Free, а не деструктор. Различие важно, потому что Free проверяет, является ли ссылка на объект нулевой, и вызывает Destroy только для ссылок, отличных от nil. В исключительных обстоятельствах класс может переопределить метод Free ...что делает его гораздо более важным назвать Free, а не Destroy. Если вы просто вызываете разрушение на свой основной объект без объяснения причин, вы, вероятно, столкнетесь с утечками памяти. – tDo

4

Объекты должны быть уничтожены, когда вы будете готовы с ними: использование .Free (которое вызывает деструктор .Destroy) или FreeAndNil.

Если вы используете интерфейсы: они подсчитываются, и, следовательно, они освобождаются для вас. То же самое для строк.

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

Например: в вашем TLight вы создаете TTimer, возможно, без владельца. В этом случае вы должны освободить таймер в деструкторе класса TLight. Если ваш TLight был TControl или TComponent, вы могли бы создать Таймер с Self как Владельцем, и он был автоматически освобожден, когда ваш экземпляр TLight был освобожден.

+0

Право собственности. Обратите внимание, что это не магия компилятора, а простой старый код Delphi, зарытый в VCL. –

+1

@ Ульрих: Да. Я думаю, что собственность - это сложный подвиг для кого-то, исходящего из собранного мусора языка: TList не имеет права собственности на свои объекты, TObjectList имеет, TComponents имеет простую форму собственности, но когда родитель элемента управления (также компонент) будет уничтожен, он будет уничтожить его, даже если у владельца установлен другой компонент. Многие ошибки в Delphi, C, C++ возникают из-за проблем с владением, и это даже наводит на поражение от опытных программистов. –

+0

Интерфейсы - это особый случай в моем опыте. Если класс имеет свойство типа интерфейса, я счел необходимым назначить nil частному полю для этого свойства в деструкторе. Уничтожение объекта не приведет к уменьшению опорных счетчиков. Может быть, я ошибаюсь, но я буду проверять его снова :) – mjn

1

Вы продолжаете ссылаться на «тип с частными варами» и спрашиваете о «разгрузке переменных». Я собираюсь выйти на конечность (поскольку, возможно, я неверно истолковал ваше сообщение), и предположим, что вы говорите о переменных класса и спрашиваете, когда эти переменные класса должны быть завершены, когда «класс выгружает». (В какой-то момент вы выполняли программирование на Java или .NET, no ;-).

Ключом к тому, что вы просите, является раздел завершения раздела. Общая компоновка блока включает 4 общих раздела, две из которых являются необязательными, инициализация и завершение.

unit Foo; 
interface 
    // put things here you want other units to see 
implementation 
    // put the *implementation* of the things from the interface here along with things 
    // you only want this unit to see. 
initialization 
    // <optional> put code here that you want to execute when this unit is "loaded" 
finalization 
    // <optional> put code here that you want to execute when this unit is "unloaded" 
end. 

Если вы говорите о экземпляра переменные типа класса, то некоторые другие ответы, которые вы уже получили (и обязаны получить) должны пролить некоторый свет на это.

+0

Спасибо. Хотя это не совсем то, что я ищу, этот простой обзор очищает туман, который все еще висит вокруг. Да, я из C# bgnd, но никогда не помешает попробовать другой язык, чтобы «заточить пилу», верно? ;) Мне нравятся секция init и finit. Думаю, я могу их использовать. –

3

Вот как я это вижу:

Примитивные типы (как целое, вещественное, двойной, расширенный), массивы, наборы, записи: они автоматически уничтожаются при выходе из области видимости.

Сводные типы (строки, типы интерфейсов, ссылки на интерфейс): они автоматически уничтожаются, когда их опорный счетчик равен нулю.

объектов из классов, которые попадают в одну из этих ситуаций: не сходит с TComponent, в список объектов, которые не реализуют права собственности или являются потомком ТСотропепЬ, но не имеет владельца, возложенные на него:

  • Когда их класс сойдет с TInterfacesObject и доступны из интерфейсной ссылки: такие же поведения от типов эталонного счетчика (смотрите выше)
  • других случаев: вызвать Object.Free или FreeAndNil (объект), чтобы уничтожить его вручную (в try..finally структура будет еще лучше)

Объекты, у которых есть владелец (потомки TComponent или находятся в объектах списка, реализующих право собственности): владелец возьмет их вовремя.

я заметил следующий комментарий от OP:

Я заметил понятие владельца. Тем не менее, я не смог передать свой собственный класс методу TTimer.Create(), так как это , ожидая TComponent. Почему они ограничивают вещи, которые будут использоваться только в формах ? Разве это не означает, что плохая привычка положить логику в ваши просмотров (форм)?

См, потомок ТСотропепЬ может быть зарегистрирован на паллете, чтобы иметь возможность использовать в конструкции времени (например, в форме). Но это не значит, что должен !! Вы можете передать свой пользовательский класс в TTimer.Create(), если он сходит с TComponent, но вам не нужно создавать его во время разработки - или даже быть владельцем потомка TForm (если вы хотите управлять его жизненным циклом, вам даже не нужен владелец!).

собственности представляет собой механизм, это, чтобы помочь людям сэкономить время ....

+0

Спасибо, что понятный язык для меня :) –

+0

Жаль, что я могу отметить два ответа, поскольку в этом ответе говорится, когда нужно уничтожать то, что и другое говорит, как это сделать –

Смежные вопросы