No processo de portar o código de C ++ para Delphi, muitas vezes precisa portar o código usando coleções STL. O conjunto de coleções oferecidas por Delphi é muito asceta e, portanto, às vezes
É difícil encontrar um substituto adequado. Às vezes, você encontra o código em que o objeto é colocado na pilha ou usa seu próprio alocador de memória.
Eu realmente não gosto do modo de atualização de dados sugerido. Para atualizar os dados, preciso recuperar o valor colocado nele na coleção, atualizar o valor e colocar o valor alterado de volta. Isso requer pelo menos duas operações de cópia adicionais. Não podemos passar um item de dados como um parâmetro var para um procedimento.
Não há como uma coleção mudar como a memória é alocada. A memória de objetos e registros é alocada de uma pilha compartilhada. Após o uso, a memória deve ser cuidadosamente devolvida à pilha. A liberação de memória corretamente nem sempre é uma tarefa trivial e leva o tempo do processador e o tempo do programador para escrever esse código. No STL, você pode especificar seu próprio alocador de memória para todos os tipos de coleções.
Esta implementação depende de registros e indicadores. Até agora, não vejo como implementar o que quero usando objetos padrão. A criação e destruição de objetos usa uma pilha de memória compartilhada. Não há como colocar objetos na pilha de chamadas. O bom e velho "objeto" é declarado depreciado e a adição de novos recursos para esse tipo não é suportada.
Esta implementação de coleção baseia -se no gerenciamento de memória do mecanismo com base nas regiões de memória digitadas. O uso de regiões de memória digitada possibilita simplificar a solução de várias tarefas:
A tarefa de liberar memória se torna mais fácil e pode ser feita muito mais rápida.
É um fato bem conhecido que um gerenciador de memória padrão deve ser seguro para threads. Apenas um thread pode acessar o gerenciador de memória a qualquer momento. Alocar e liberar memória usa mecanismos de exclusão mútua e não é uma operação rápida, especialmente se a memória for fortemente desfragmentada. Ao usar uma região de memória digitada separada, nos referimos ao gerenciador de memória padrão apenas no momento de aumentar a memória necessária e excluir a estrutura após seu uso.
Suporte para estruturas básicas com a capacidade de especificar um alocador de memória. Os elementos da lista são acessados através de ponteiros. Como regra, a memória para valores está localizada na chamada região de memória segmentada, que não será movida durante a operação. Se for necessário aumentar a memória de uma região, um segmento de memória adicional será alocado para ela. Isso significa que podemos acessar itens de dados localizados nessa região através de um ponteiro.
Para matrizes, usamos a chamada região de memória contígua. Os itens de dados são acessados por meio de um índice. Se necessário, aumente a memória da região, um segmento com um tamanho grande é alocado para ela e os dados do segmento de memória atual são copiados para o novo segmento. Depois de copiar os dados, o segmento antigo será excluído.
Por fim, trabalhar com ponteiros é muito conveniente e eficiente. O código se torna muito mais simples e conciso. No entanto, se você não tem experiência com ponteiros, é fácil "atirar no pé". Para os fãs de encapsulamento, você pode agregar a estrutura desejada como um campo privado. Em seguida, abrimos apenas a parte necessária da interface, substituindo os métodos e propriedades necessários na seção pública. Se colocarmos a opção em linha, evitamos custos adicionais. O compilador Delphi não gerará código para métodos substituídos. No local da chamada do método, haverá uma chamada direta para o método da estrutura agregada.
TsgTuple<T1, ...> tuplas genéricasTsgArray<T> Array genérico com alocação de memória de uma região de memória compartilhadaTsgList<T> Lista genérica de valoresTsgRecordList<T> Lista genérica de valores acessados por ponteiroTsgLinkedList<T> Lista bidirecional genéricaTsgForwardList<T> Lista unidirecional genéricaTsgHashMap<Key, T> dicionário não ordenado genéricoTsgMap<Key, T> dicionário ordenado genérico baseado em 2-3 árvoreTsgSet<Key> Conjunto genérico com base em 2-3 árvoresTsgPointerArray List de ponteirosTsgPointerList Lista de valores achados de valores acessados por ponteiroTCustomLinkedList link bidirecional não titular ListaTsgCustomTree Dicionário não topado com base em 2-3 árvores Começamos a adicionar iteradores Delphi. Agora podemos usar a construção for p in List do; O mais interessante é que usamos o registro para implementar o iterador e ele funciona! Comparado ao uso de objetos, o código gerado é muito mais eficiente e, o que é agradável, sem chamadas para a pilha, a variável para o iterador está localizada na pilha. Isso acabou sendo uma surpresa bastante agradável para mim!
A capacidade de especificar um alocador de memória também significa que trabalhamos principalmente com registros. Normalmente, alguma estrutura usa uma ou mais regiões de memória, que é um gerenciador de memória simples. Depois de usar a estrutura, temos a oportunidade de retornar toda a memória ocupada, liberando a região da memória. Temos limitações usando a herança. Em alguns casos, podemos substituir a herança por agregação e ajudantes. Normalmente, para implementar coleções, isso não é um problema. O uso de registros permite que as coleções sejam empilhadas. Isso às vezes é muito conveniente.
Um pool de objetos permite gerenciar a reutilização de estruturas ao criar objetos é intensiva em memória ou quando um número limitado de objetos de um determinado tipo pode ser criado.
Se pararmos de usar algo, nem sempre vale a pena excluir a estrutura ou objeto. Muitas vezes, o objeto deve ser recriado.