Por que std :: alocadores não são tão populares? [fechadas]

8

Com as tendências mais recentes sobre aplicativos C e C ++, e com os últimos anos, quero dizer que os std::allocators sejam usados ​​com muito mais frequência do que realmente é.

Os aplicativos modernos geralmente são multithread ou com forma de simultaneidade, e gerenciam uma quantidade significativa de memória, especialmente em alguns campos, como jogos e aplicativos multimídia; portanto, o alto custo usual das alocações / desalocações aumenta e afeta os desempenhos ainda mais do que em aplicativos antigos.

Mas, pelo que vejo esse tipo de gerenciamento de memória através de std::allocators, não é popular, não posso nem contar uma biblioteca que conheço, que esteja usando qualquer lógica sobre uma maneira padronizada de gerenciar memória.

Existe uma verdadeira razão pela qual std::allocatornão é popular? Razões técnicas?

user2485710
fonte
2
porque é difícil de usar?
Bryan Chen
4
@BryanChen, o que você quer dizer com isso? o alocador geralmente é o segundo argumento em qualquer contêiner padrão; std::allocatoré extremamente fácil de usar.
User2485710
1
Você está perguntando por std::allocatorque (que é basicamente um invólucro newe posicionamento new) não é tão usado? Ou você está se perguntando por que o conceito C ++ de Allocatorwidley não é usado? São duas perguntas diferentes.
Dave S
O @DaveS é mais parecido com a primeira opção, mas não entendo por que difere da segunda, você quer dizer algo relacionado à portabilidade do próprio código?
User2485710
1
@BryanChen você pode mostrar por que é difícil? quais são as armadilhas?
User2485710

Respostas:

13

Existem duas perguntas aqui:

1) Por que não é std::allocatormais usado?

A resposta curta é porque, para a maioria dos usos, usar newe deleteé suficiente.

Primeiro, uma breve visão geral do objetivo do C ++ 11 Allocator. Basicamente, quando você faz um new Foo, ele aloca memória e depois constrói o objeto nessa memória.

Mas e se você precisasse alocar memória e construir como duas etapas separadas. O exemplo clássico disso é std::vector, que pode alocar memória sem inicializá-la imediatamente, mas constrói os elementos à medida que você os adiciona ao contêiner. O objetivo std::allocatoré fornecer uma interface para executar essas etapas separadas de maneira uniforme.

No entanto, para a maioria dos usuários, eles não precisam desse nível de controle, porque é apenas mais uma coisa a ser lembrada ao limpar suas exceções.

2) Por que mais coisas não usam o conceito de C ++ Allocator?

Principalmente a necessidade não existe. As únicas classes que tendem a usá-las são aquelas que desejam dar a seus usuários mais controle sobre a fonte da memória que eles alocam. Os contêineres da biblioteca Padrão são gravados dessa maneira para que o usuário possa tomar essas decisões, se quiserem, mas eles usam o alocador normal como padrão.

Dave S
fonte
3
+1 para o ponto 1, que é a verdadeira razão na minha opinião. Não é "difícil de usar", que discordo completamente de ter escrito muitos alocadores de memória para vários conjuntos de memórias: o alocador é muito fácil de escrever e é apenas uma série de métodos compatíveis com a interface. Como você gerenciar a memória é com você, pode ser fácil ou pode ser difícil (chunking com coalescentes mecanismos)
Marco A.
5

A popularidade de um conceito de linguagem ou biblioteca está em uma correlação inversa com sua complexidade subjacente.

O std::allocatorconceito é de baixo nível e, como tal, apresenta possíveis armadilhas. Ter um alocador personalizado adiantado provavelmente será considerado uma otimização prematura. Além disso, de maneira semelhante a outros conceitos de baixo nível, geralmente é preferível delegar o gerenciamento de alocação de trabalho a bibliotecas (stdlib, boost), a menos que a sobrecarga de lidar com a complexidade de suas próprias alocações seja absolutamente justificada.

Considere os ponteiros como apenas um exemplo de apoio desta tese. Adoramos ponteiros por seu acesso irrestrito à memória e zero sobrecarga, mas em C ++ sabemos melhor usar wrappers com escopo / raii para gerenciar a complexidade, ou seja, até que precisemos explicitamente do desempenho ou que todos possamos concordar com alguma semântica não-proprietária para certos casos de uso bem definidos.

Ao usar um std :: allocator é preciso considerar a ABI e as compatibilidades API, e pergunta maravilhosa, como o comportamento desejado quando o código está envolvido
std::vector<T,A1>().swap(std::vector<T,A2>())com diferente (e stateful!) A1E A2alocadores. Além disso, alguns contêineres nem usam o alocador da maneira que você pretendia! Dê uma olhada std::list<T,A>ou std::map<K,T,C,A>por exemplo. A expectativa natural é que o alocador seja usado para alocar objetos do tipo Tpara uma lista ou a pair<const K,T>para um mapa; no entanto, na prática, uma implementação de biblioteca padrão solicita a alocação de um nó de lista ou mapa, e mesmo o tamanho do nó pode ser diferente entre versões de lançamento e depuração. Alocadores personalizados são repletos de minúcias, e a complexidade e os detalhes adicionados são desnecessários para as tarefas de programação mais comuns.

mockinterface
fonte
Qual é a sobrecarga de usar o wrapper RAII std::unique_ptr<T>para possuir memória em vez de T *?
David Stone
@DavidStone Como eu acho que você já sabia (fazendo disso uma pergunta complicada), a resposta é zero.
underscore_d
2

Um alocador é uma política injetada em dependência, nos contêineres padrão. Ele existe principalmente para permitir que o código do cliente separe a política de alocação da instanciação, em contêineres já implementados .

O problema aparece quando você precisa usar std :: containers, e a política de alocação padrão (conforme implementada por std :: alocador) não se adequa às necessidades do seu projeto (por exemplo, você deseja que a implementação std :: vector seja lançada se houver mais 1024 objetos são alocados, você deseja usar um conjunto de memórias ou garantir que todas as alocações sejam pré-alocadas em uma determinada área de memória e assim por diante).

Se você não pudesse injetar um alocador diferente nos contêineres, isso o proibiria de usar o std :: containers todo em alguns projetos.

Para contornar isso (e garantir que você ainda possa usar os std :: containers quando tiver requisitos complexos de memória), o alocador é um parâmetro de modelo para os containers.

Para responder à sua pergunta : a maioria das pessoas não usa std :: alocadores porque, quando escrevem o código do cliente, têm controle total das alocações - portanto, não precisam injetar uma política de alocação - e, quando usam o código da biblioteca, o std :: alocador é geralmente suficiente.

utnapistim
fonte