¿Por qué std :: allocators no son tan populares? [cerrado]

8

Con las últimas tendencias sobre las aplicaciones C y C ++, y con las últimas me refiero a los últimos años, esperaba ver que las std::allocators se usaran con más frecuencia de lo que realmente es.

Las aplicaciones modernas generalmente son multiproceso o con una forma de concurrencia en ellas, y manejan una cantidad significativa de memoria, especialmente en algunos campos como juegos y aplicaciones multimedia; Por lo tanto, el alto costo habitual de la asignación / reparto de ubicaciones aumenta e impacta el rendimiento aún más que en las aplicaciones antiguas.

Pero por lo que puedo ver, este tipo de administración de memoria a través de std::allocators no es popular, ni siquiera puedo contar 1 biblioteca que conozca, que esté utilizando cualquier razón sobre una forma estandarizada de administrar la memoria.

Hay una razón real por la que std::allocatorno es popular? Razones técnicas?

usuario2485710
fuente
2
porque es dificil de usar?
Bryan Chen
44
@BryanChen, ¿qué quieres decir con eso? el asignador suele ser el segundo argumento en cualquier contenedor estándar, std::allocatores extremadamente fácil de usar.
user2485710
1
¿Se pregunta por qué std::allocator(que es básicamente una envoltura newy ubicación new) no se usa tanto? ¿O se pregunta por qué Allocatorno se usa el concepto de C ++ de widley? Son dos preguntas diferentes.
Dave S
@DaveS se parece más a la primera opción, pero no entiendo por qué difiere de la segunda, ¿quieres decir algo relacionado con la portabilidad del código en sí?
user2485710
1
@BryanChen, ¿puedes mostrar por qué es difícil? ¿Cuáles son las trampas?
user2485710

Respuestas:

13

Aquí hay dos preguntas:

1) ¿Por qué no se std::allocatorusa más?

La respuesta corta es porque para la mayoría de los usos, usar newy deletees suficiente.

Primero, una breve descripción de para qué está destinado el concepto de C ++ 11 Allocator. Básicamente, cuando haces un new Foo, ambos asignan memoria y luego construyen el objeto en esa memoria.

Pero, ¿qué pasaría si necesitara asignar memoria y construir como dos pasos separados? El ejemplo clásico de esto es std::vector, que puede asignar memoria sin inicializarla inmediatamente, pero luego construye los elementos a medida que los agrega al contenedor. El objetivo std::allocatores proporcionar una interfaz para realizar esos pasos por separado de manera uniforme.

Sin embargo, para la mayoría de los usuarios, no necesitan ese nivel de control, porque es solo otra cosa que debe recordar al limpiar sus excepciones.

2) ¿Por qué más cosas no hacen uso del concepto de C ++ Allocator?

Principalmente la necesidad no está ahí. Las únicas clases que tienden a usarlas son las que desean dar a sus usuarios más control sobre la fuente de la memoria que asignan. Los contenedores de la biblioteca estándar se escriben de esa manera para que el usuario pueda tomar esas decisiones si así lo desea, pero por defecto usan el asignador normal.

Dave S
fuente
3
+1 para el punto 1, que es la verdadera razón en mi opinión. No "es difícil de usar", que no estoy de acuerdo con haber escrito muchos asignadores de memoria para varios grupos de memoria: el asignador es bastante fácil de escribir y es solo una serie de métodos compatibles con la interfaz. La forma en que maneja la memoria depende de usted, puede ser fácil o difícil (fragmentación con mecanismos de fusión)
Marco A.
5

La popularidad de un lenguaje o un concepto de biblioteca está en una correlación inversa con su complejidad subyacente.

El std::allocatores un concepto de bajo nivel y, como tal, tiene dificultades potenciales. Es probable que tener un asignador personalizado por adelantado se considere una optimización prematura. Además, de manera similar a otros conceptos de bajo nivel, generalmente se prefiere delegar la administración de la asignación de trabajo a las bibliotecas (stdlib, boost) a menos que la sobrecarga de manejar la complejidad de sus propias asignaciones esté absolutamente justificada.

Considere los punteros como solo un ejemplo de apoyo de esta tesis. Nos encantan los punteros por su acceso sin restricciones a la memoria y cero sobrecarga, pero en C ++ sabemos que es mejor usar envoltorios con alcance / raii para administrar la complejidad, hasta que explícitamente necesitemos el rendimiento o todos podamos acordar alguna semántica no propietaria para ciertos casos de uso bien definidos.

Al usar un std :: allocator, debe tener en cuenta las compatibilidades ABI y API, y una pregunta maravillosa, como el comportamiento deseado cuando el código se involucra
std::vector<T,A1>().swap(std::vector<T,A2>())con diferentes (y con estado) A1y A2asignadores. Además, ¡algunos contenedores ni siquiera usan el asignador de la manera que usted pretendía! Echa un vistazo a std::list<T,A>o std::map<K,T,C,A>por ejemplo. La expectativa natural es que el asignador se use para asignar objetos de tipo Tpara una lista o un pair<const K,T>mapa, sin embargo, en la práctica, una implementación de biblioteca estándar pedirá asignar un nodo de lista o mapa, e incluso el tamaño del nodo puede ser diferente entre versiones de lanzamiento y depuración. Los asignadores personalizados están repletos de minucias, y la complejidad y los detalles adicionales son innecesarios para las tareas de programación más comunes.

interfaz ficticia
fuente
¿Cuál es la sobrecarga de usar el contenedor RAII std::unique_ptr<T>para poseer memoria en lugar de hacerlo T *?
David Stone
@DavidStone Como supongo que ya lo sabías (por lo que es una pregunta capciosa), la respuesta es cero.
underscore_d
2

Un asignador es una política de dependencia inyectada en los contenedores estándar. Está allí principalmente para permitir que el código del cliente separe la política de asignación de la creación de instancias, en contenedores ya implementados .

El problema aparece cuando necesita usar std :: container, y la política de asignación predeterminada (implementada por std :: allocator) no se ajusta a las necesidades de su proyecto (por ejemplo, si desea que la implementación std :: vector se lance si hay más se asignan más de 1024 objetos, desea utilizar un grupo de memoria o asegurarse de que todas las asignaciones estén preasignadas en un área de memoria determinada, etc.)

Si no pudiera inyectar un asignador diferente en los contenedores, esto le prohibiría usar std :: container en algunos proyectos.

Para evitar esto (y asegurarse de que todavía puede usar los std :: contenedores cuando tiene requisitos de memoria complejos), el asignador es un parámetro con plantilla para los contenedores.

Para responder a su pregunta : la mayoría de las personas no usan std :: allocators porque cuando escriben código de cliente tienen control total de las asignaciones, por lo que no necesitan inyectar una política de asignación, y cuando usan código de biblioteca, el std :: asignador suele ser suficiente.

utnapistim
fuente