Очистить TList или TObjectList

Я немного озадачен тем, что использовать для хранения объектов в списке. До сих пор я использовал TList и освобождал каждый элемент в цикле. Затем я обнаружил TObjectList, которые делают это автоматически из Free. Затем я увидел это из документа TList.Clear:

Вызовите Clear, чтобы очистить массив Items, и установите Count в 0. Clear также освобождает память, используемую для хранения массива Items, и устанавливает Capacity в 0.

Так что это в основном то же самое. Так

для TList

mylist.Clear;
myList.Free;

такое же, как для TObjectList?

myList.Free;

Можно ли использовать TObjectList только для элементов в качестве классов или я могу хранить записи?


person Roland Bengtsson    schedule 02.05.2012    source источник
comment
Та часть, которую вы цитируете, в основном такая же, только если вы не читаете внимательно документацию TObjectList: если свойство OwnsObjects установлено в true (по умолчанию), TObjectList управляет памятью своих объектов, освобождая объект при переназначении его индекса; при удалении из списка методом Удалить, Удалить или Очистить; или когда сам экземпляр TObjectList уничтожается. Документация TList ничего не говорит об этом поведении. Это фундаментальное различие между двумя классами.   -  person Rob Kennedy    schedule 02.05.2012


Ответы (5)


<сильный>1. TList не освободит элементы как с Clear, так и с Free.

Список.Очистить;

Просто установит aList.Count := 0, не освобождая элементы aList.Items[]. Так у вас будет утечка памяти. Вам понадобится явное бесплатное как таковое:

for i := 0 to aList.Count-1 do
  TObject(aList[i]).Free;

Но это то, что делает TObjectList... :)

По поводу TObjectList стоит сказать, что TObjectList.Destroy звонит Clear.

So

aObjectList.Clear;
aObjectList.Free;

точно такой же, как

aObjectList.Free;

<сильный>2. Чтобы сохранить список записей, вы можете использовать динамический массив.

Вы получите все TList методов (и больше) с нашим оболочка динамического массива. То есть Add / Delete / Clear / Count / IndexOf / Find...

Он имеет встроенные функции сериализации (в двоичном формате или JSON), автоматической сортировки и сравнения (с использованием RTTI), которых нет в TList/TObjectList. Начиная с Delphi 5 и выше.

В более современной версии Delphi вы можете использовать универсальные шаблоны для обработки динамического массива, если вы не хотите использовать стороннюю библиотеку.

person Arnaud Bouchez    schedule 02.05.2012
comment
Просто уточнение по поводу TObjectList. У него есть свойство: OwnsObjects (по умолчанию = true), которое определяет, освобождаются ли объекты в списке при удалении элементов. - person LU RD; 02.05.2012
comment
@LURD Ты прав. Это свойство может быть удобным, но также и вводящим в заблуждение: вы можете предположить, что объекты будут освобождены, но если вы установите OwnObjects := false где-нибудь в коде (даже во время выполнения), вы легко получите утечку памяти или ресурсов: так что используйте их с осторожностью! Я предпочитаю четкое разделение TList / TObjectList. - person Arnaud Bouchez; 02.05.2012

Это не то же самое, TList.Clear только освобождает память, выделенную для хранения указателей, а не объектов, на которые они указывают. Чтобы избежать утечек памяти, вам нужно освободить память самостоятельно, как вы это делали ранее, или использовать TObjectList.

Чтобы ответить на второй вопрос, TObjectList не поддерживает хранение записей. В этом случае вам нужно использовать TList (или что-то еще).

person Ondrej Kelle    schedule 02.05.2012
comment
Однако знайте, что управление записями в TList требует некоторых усилий. - person NGLN; 02.05.2012

Прочтите внимательнее, что говорится в документации:

Clear также освобождает память, используемую для хранения массива Items.

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

person Remy Lebeau    schedule 02.05.2012

Если вы используете последнюю версию Delphi, я предлагаю вам использовать общий список.

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

Например, если у вас есть:

TMyObject = class(TObject);

Затем вы составляете список следующим образом:

TMyObjectList = TObjectList<TMyObject>;

В Embarcadero Wiki есть статья:

http://docwiki.embarcadero.com/CodeExamples/XE8/en/Generics_Collections_TObjectList_(Delphi)

person Birger    schedule 02.05.2012

На самом деле просмотр кода TObjectList в contnrs.pas OwnObjects ничего не дает. FOwnObjects — это переменная, объявленная в приватной части TObjectList, которая нигде в коде TObjectList не используется (кроме только присвоения значения), и в ней нет переопределенной процедуры Clear.

Так что боюсь надо освобождать память так же как и в TList.

person Gonzalo    schedule 21.11.2013
comment
Свойство TObjectList.OwnsObjects истинно по умолчанию. Вы можете изменить значение свойства после создания. Если это свойство имеет значение true при вызове TObjectList.Free, все объекты в списке будут автоматически освобождены. - person LU RD; 21.11.2013