Inicializar un mapa std::cuando el tamaño se conoce de antemano


Me gustaría inicializar un std::map. Por ahora estoy usando ::insert pero siento que estoy perdiendo algo de tiempo computacional ya que ya sé el tamaño que quiero asignar. ¿Hay una manera de asignar un mapa de tamaño fijo y luego llenar el mapa ?

Author: vanna, 2012-10-24

4 answers

No, los miembros del mapa se almacenan internamente en una estructura de árbol. No hay manera de construir el árbol hasta que sepa las claves y los valores que se van a almacenar.

 31
Author: Bo Persson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-04 13:30:52

La respuesta corta es: sí, esto es posible, pero no es trivial. Necesita definir un asignador personalizado para su mapa. La idea básica es que su asignador personalizado reservará un solo bloque de memoria para el mapa. Como el mapa requiere nuevos nodos, el asignador simplemente les asignará direcciones dentro del bloque preasignado. Algo como esto:

std::map<KeyType, ValueType, std::less<KeyType>, MyAllocator> myMap;

myMap.get_allocator().reserve( nodeSize * numberOfNodes );

Sin embargo, hay una serie de problemas con los que tendrá que lidiar.

Primero, no sabes realmente el tamaño de cada uno nodo de mapa o cuántas asignaciones realizará el mapa. Estos son detalles de implementación interna. Puede experimentar para averiguarlo, pero no puede asumir que los resultados se mantendrán en diferentes compiladores (o incluso en futuras versiones del mismo compilador). Por lo tanto, no debe preocuparse por asignar un mapa de tamaño "fijo". Más bien, su objetivo debe ser reducir el número de asignaciones requeridas a un puñado.

En segundo lugar, esta estrategia se vuelve un poco más compleja si quieres eliminación de soporte.

Tercero, no olvide los problemas de alineación de la memoria. Los punteros que devuelve el asignador deben estar correctamente alineados para los diversos tipos de objetos que almacenará la memoria.

Dicho todo esto, antes de probar esto, asegúrese de que sea necesario. La asignación de memoria puede ser muy costosa, pero aún así no debe asumir que es un problema para su programa. Mide para averiguarlo. También debe considerar estrategias alternativas que permitan la pre-asignación de forma más natural. Por ejemplo, una lista ordenada o un std::unordered_map.

 19
Author: Peter Ruderman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-24 14:13:12

Estás hablando de block allocators. Pero es difícil de implementar. Mida antes de pensar en cosas tan difíciles. De todos modos Boost tiene algunos artículos sobre la implementación del asignador de bloques. O utilizar el mapa preasignado ya implementado Stree

 2
Author: Denis Ermolin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-24 12:49:54

No estoy seguro de si esto responde a tu pregunta, pero Aumenta.Container tiene un flat_map en el que puede reservar espacio. Básicamente puede ver esto como un vector ordenado de pares (clave, valor). Pero, de nuevo, si su entrada ya era constante, no usaría un std::map en primer lugar. Consejo adicional: si también sabe que su entrada está ordenada, puede usar insertar con sugerencia para un rendimiento máximo.

 1
Author: gast128,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-04 13:37:51