Dans le processus de portage du code de C ++ à Delphi, il faut très souvent le code de port à l'aide de collections STL. L'ensemble des collections offerts par Delphi est très ascétique et donc parfois
Il est difficile de trouver un remplacement approprié. Parfois, vous rencontrez le code où l'objet est placé dans la pile ou utilise son propre allocateur de mémoire.
Je n'aime vraiment pas le mode de rafraîchissement des données suggéré. Pour mettre à jour les données, je dois récupérer la valeur placée de la collection, mettre à jour la valeur, puis remettre la valeur modifiée. Cela nécessite au moins deux opérations de copie supplémentaires. Nous ne pouvons pas transmettre un élément de données en tant que paramètre VAR à une procédure.
Il n'y a aucun moyen pour une collection de changer la façon dont la mémoire est allouée. La mémoire pour les objets et les enregistrements est allouée à partir d'un tas partagé. Après utilisation, la mémoire doit être soigneusement retournée au tas. La libération de la mémoire correctement n'est pas toujours une tâche triviale, et il faut à la fois le temps du processeur et le temps du programmeur pour écrire ce code. Dans STL, vous pouvez spécifier votre propre allocateur de mémoire pour toutes sortes de collections.
Cette implémentation repose sur les enregistrements et les pointeurs. Jusqu'à présent, je ne vois aucun moyen d'implémenter ce que je veux utiliser des objets standard. La création et la destruction d'objets utilisent un tas de mémoire partagée. Il n'y a aucun moyen de placer des objets sur la pile d'appels. Le bon ancien "objet" est déclaré déprécié et l'ajout de nouvelles fonctionnalités pour ce type n'est pas pris en charge.
Cette implémentation de la collection repose sur la gestion de la mémoire du mécanisme basé sur les régions de mémoire typées. L'utilisation de régions de mémoire typé permet de simplifier la solution d'un certain nombre de tâches:
La tâche de libération de la mémoire devient plus facile et peut être fait beaucoup plus rapidement.
C'est un fait bien connu qu'un gestionnaire de mémoire standard doit être en file d'attente. Un seul thread peut accéder au gestionnaire de mémoire à tout moment. L'allocation et la libération de la mémoire utilisent des mécanismes d'exclusion mutuelle et n'est pas une opération rapide, surtout si la mémoire est fortement défragmentée. Lorsque nous utilisons une région de mémoire typtée distincte, nous nous référons au gestionnaire de mémoire standard qu'au moment de l'augmentation de la mémoire requise et de la suppression de la structure après son utilisation.
Prise en charge des structures de base avec la possibilité de spécifier un allocateur de mémoire. Les éléments de la liste sont accessibles via des pointeurs. En règle générale, la mémoire des valeurs est située dans la région de la mémoire soi-disant segmentée, qui ne sera pas déplacée pendant le fonctionnement. S'il est nécessaire d'augmenter la mémoire d'une région, un segment de mémoire supplémentaire est alloué pour cela. Cela signifie que nous pouvons accéder aux éléments de données situés dans une telle région via un pointeur.
Pour les tableaux, nous utilisons la région de la mémoire dite contigu. Les éléments de données sont accessibles via un index. Si nécessaire, augmentez la mémoire de la région, un segment de grande taille est alloué pour l'informatique et les données du segment de mémoire actuel sont copiées dans le nouveau segment. Après la copie des données, l'ancien segment sera supprimé.
En fin de compte, travailler par des pointeurs est très pratique et efficace. Le code devient beaucoup plus simple et plus concis. Cependant, si vous n'avez aucune expérience avec les pointeurs, il est facile de "vous tirer dessus au pied". Pour les fans de l'encapsulation, vous pouvez agréger la structure souhaitée en tant que champ privé. Ensuite, nous ouvrons uniquement la partie nécessaire de l'interface en remplaçant les méthodes et propriétés requises dans la section publique. Si nous mettons l'option en ligne, nous évitons les coûts supplémentaires. Le compilateur Delphi ne générera pas de code pour les méthodes remplacées. À la place de l'appel de la méthode, il y aura un appel direct à la méthode de la structure agrégée.
TsgTuple<T1, ...> Tuples génériquesTsgArray<T> Tableau générique avec allocation de mémoire à partir d'une région de mémoire partagéeTsgList<T> Liste générique de valeursTsgRecordList<T> Liste générique des valeurs accessibles par pointeurTsgLinkedList<T> Liste liée bidirectionnelle génériqueTsgForwardList<T> Liste liée unidirectionnelle génériqueTsgHashMap<Key, T> dictionnaire générique non ordonnéTsgMap<Key, T> dictionnaire ordonné générique basé sur 2-3 arbreTsgSet<Key> Ensemble générique basé sur 2-3 arbresTsgPointerArray Liste des pointeursTsgPointerList LISTE UNTYPED DES VALEURS CONCUSÉ PAR POINTERTCustomLinkedList Liste liée bidirectionnelle non typéeTsgCustomTree non type dictionnaire basé sur 2-3 arbres Nous avons commencé à ajouter des itérateurs Delphi. Maintenant, nous pouvons utiliser la construction for p in List do; La chose la plus intéressante est que nous utilisons l'enregistrement pour implémenter l'itérateur et cela fonctionne! Par rapport à l'utilisation d'objets, le code généré est beaucoup plus efficace et, ce qui est bien, aucun appel au tas, la variable de l'itérateur est située sur la pile. Cela s'est avéré être une surprise assez agréable pour moi!
La possibilité de spécifier un allocateur de mémoire signifie également que nous travaillons principalement avec les enregistrements. En règle générale, une structure utilise une ou plusieurs régions de mémoire, qui est un simple gestionnaire de mémoire. Après avoir utilisé la structure, nous avons l'opportunité de retourner toute la mémoire occupée par la libération de la région de la mémoire. Nous avons des limites en utilisant l'héritage. Dans certains cas, nous pouvons remplacer l'héritage par l'agrégation et les aides. En règle générale pour la mise en œuvre de collections, ce n'est pas un problème. L'utilisation d'enregistrements permet d'empiler les collections. C'est parfois très pratique.
Un pool d'objets vous permet de gérer la réutilisation des structures lors de la création d'objets est à forte intensité de mémoire ou lorsqu'un nombre limité d'objets d'un certain type peut être créé.
Si nous cessons d'utiliser quelque chose, cela ne vaut pas toujours la peine de supprimer la structure ou l'objet. Souvent, l'objet doit être recréé.