В процессе портирования кода из C ++ в Delphi очень часто приходится переносить код, используя коллекции STL. Набор коллекций, предлагаемых Delphi, очень аскетичен и поэтому иногда
Трудно найти подходящую замену. Иногда вы сталкиваетесь с кодом, где объект помещается в стек или использует свой собственный распределитель памяти.
Мне действительно не нравится предложенный режим обновления данных. Чтобы обновить данные, мне нужно получить значение, размещенное в нем из коллекции, обновить значение, а затем вернуть измененное значение обратно. Это требует как минимум двух дополнительных операций копирования. Мы не можем передать элемент данных в качестве параметра VAR в процедуру.
Коллекция не может изменить, как распределяется память. Память для объектов и записей выделяется из одной общей кучи. После использования память должна быть тщательно возвращена в кучу. Правильное освобождение памяти не всегда является тривиальной задачей, и требуется как время процессора, так и время программиста, чтобы написать этот код. В STL вы можете указать свой собственный распределитель памяти для всех видов коллекций.
Эта реализация зависит от записей и указателей. До сих пор я не вижу возможности реализовать то, что я хочу, используя стандартные объекты. Создание и разрушение объектов использует общую кучу памяти. Нет возможности разместить объекты в стек вызовов. Старый добрый «объект» объявлен на устаревшем, и добавление новых функций для этого типа не поддерживается.
Эта реализация коллекции зависит от управления памятью механизма на основе типированных областей памяти. Использование напечатанных областей памяти позволяет упростить решение ряда задач:
Задача освобождения памяти становится проще и может быть сделана намного быстрее.
Это хорошо известный факт, что стандартный диспетчер памяти должен быть безопасным. Только один поток может получить доступ к диспетчере памяти в любой момент времени. Распределение и освобождение памяти использует механизмы взаимного исключения и не является быстрой работой, особенно если память сильно дефрагментация. При использовании отдельной печатной области памяти мы ссылаемся на стандартный диспетчер памяти только в момент увеличения необходимой памяти и удаления структуры после ее использования.
Поддержка основных структур с возможностью указать распределитель памяти. Элементы списка доступны через указатели. Как правило, память для значений находится в так называемой сегментированной области памяти, которая не будет перемещена во время работы. Если необходимо увеличить память области, для нее выделяется дополнительный сегмент памяти. Это означает, что мы можем получить доступ к элементам данных, расположенных в таком регионе, посредством указателя.
Для массивов мы используем так называемую область смежной памяти. Доступны элементы данных через индекс. При необходимости увеличьте память региона, для него выделяется сегмент с большим размером, а данные из текущего сегмента памяти копируются в новый сегмент. После копирования данных старый сегмент будет удален.
В конечном счете, работа через указатели очень удобно и эффективно. Код становится намного проще и более кратким. Однако, если у вас нет опыта с указателями, легко «стрелять в ногу». Для поклонников инкапсуляции вы можете объединить желаемую структуру в качестве частного поля. Затем мы открываем только необходимую часть интерфейса, переопределив необходимые методы и свойства в публичном разделе. Если мы разместим встроенный вариант, мы избегаем дополнительных затрат. Компилятор Delphi не будет генерировать код для переопределенных методов. На месте вызова метода будет прямой вызов методу совокупной структуры.
TsgTuple<T1, ...> общие кортежиTsgArray<T> generic массив с распределением памяти из общей области памятиTsgList<T> общий список значенийTsgRecordList<T> общий список значений, доступ к которому доступен по указателюTsgLinkedList<T> общий двунаправленный связанный списокTsgForwardList<T> общий однонаправленный связанный списокTsgHashMap<Key, T> generic Неупопорядоченный словарьTsgMap<Key, T> Generic упорядоченный словарь на основе 2-3 дереваTsgSet<Key> Общий набор на основе 2-3 деревьевTsgPointerArray Untyped Sist of PointersTsgPointerList нетипированный список значений, доступных по указателюTCustomLinkedList нетипированный двунаправленный список связанного спискаTsgCustomTree Untyped Dictionary на основе 2-3 деревьев Мы начали добавлять итераторы Delphi. Теперь мы можем использовать конструкцию for p in List do; Самое интересное, что мы используем запись для реализации итератора, и он работает! По сравнению с использованием объектов сгенерированный код гораздо более эффективен и, что приятно, нет вызовов в кучу, переменная для итератора находится в стеке. Это оказалось для меня довольно приятным сюрпризом!
Возможность указать распределитель памяти также означает, что мы работаем в основном с записями. Как правило, в некоторой структуре используется один или несколько областей памяти, что является простым диспетчер памяти. После использования структуры у нас есть возможность вернуть всю память, занятую путем освобождения области памяти. У нас есть ограничения с использованием наследования. В некоторых случаях мы можем заменить наследование агрегацией и помощниками. Как правило, для реализации коллекций, это не проблема. Использование записей позволяет сложить коллекции. Иногда это очень удобно.
Пул объектов позволяет вам управлять повторным использованием структур при создании объектов, интенсивное или когда может быть создано ограниченное количество объектов определенного типа.
Если мы прекратим что -то использовать, это не всегда стоит удалить структуру или объект. Часто объект должен быть воссоздан.