¿Cuál es la forma correcta de inicializar un mapa estático? ¿Necesitamos una función estática que lo inicialice?
448
Usando C ++ 11:
#include <map>
using namespace std;
map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
Usando Boost.Assign :
#include <map>
#include "boost/assign.hpp"
using namespace std;
using namespace boost::assign;
map<int, char> m = map_list_of (1, 'a') (3, 'b') (5, 'c') (7, 'd');
La mejor manera es usar una función:
fuente
extern
las variables no tendrán sus valores correctos en este "antes del constructor principal en tiempo de ejecución" si el compilador solo vio laextern
declaración, pero aún no se ha encontrado con la definición de variable real .const map<int,int> m = create_map()
(y, por lo tanto, inicializar miembros constantes de una clase en la lista de inicialización:struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
No es un problema complicado hacer algo similar para impulsar. Aquí hay una clase con solo tres funciones, incluido el constructor, para replicar lo que hizo (casi).
Uso:
El código anterior funciona mejor para la inicialización de variables globales o miembros estáticos de una clase que debe inicializarse y no tiene idea de cuándo se usa primero, pero desea asegurarse de que los valores estén disponibles en ella.
Si dice, debe insertar elementos en un std :: map existente ... aquí hay otra clase para usted.
Uso:
Véalo en acción con GCC 4.7.2 aquí: http://ideone.com/3uYJiH
############### TODO A CONTINUACIÓN ES OBSOLETO #################
EDITAR : La
map_add_values
clase a continuación, que era la solución original que sugerí, fallaría cuando se trata de GCC 4.5+. Consulte el código anterior para ver cómo agregar valores al mapa existente.Uso:
NOTA: Anteriormente utilicé un
operator []
para agregar los valores reales. Esto no es posible como lo comentó dalle.##################### FIN DE LA SECCIÓN OBSOLETA #####################
fuente
operator[]
solo toma un solo argumento.error: conflicting declaration ‘map_add_values<int, int> my_map’
error: ‘my_map’ has a previous declaration as ‘std::map<int, int> my_map’
Aquí hay otra forma que usa el constructor de datos de 2 elementos. No se necesitan funciones para inicializarlo. No hay código de terceros (Boost), no hay funciones u objetos estáticos, no hay trucos, solo C ++ simple:
Desde que escribí esta respuesta, C ++ 11 está fuera. Ahora puede inicializar directamente los contenedores STL utilizando la nueva función de lista de inicializadores:
fuente
Por ejemplo:
Si map es un miembro de datos de una clase, puede inicializarlo directamente en el encabezado de la siguiente manera (desde C ++ 17):
fuente
Envolvería el mapa dentro de un objeto estático y pondría el código de inicialización del mapa en el constructor de este objeto, de esta manera está seguro de que el mapa se crea antes de que se ejecute el código de inicialización.
fuente
Solo quería compartir una solución pura de C ++ 98:
fuente
Puedes probar:
fuente
{1, 2}
lugar destd::pair<int, int>(1, 2)
.Esto es similar a
PierreBdR
, sin copiar el mapa.fuente
Si está atascado con C ++ 98 y no desea usar boost, aquí está la solución que uso cuando necesito inicializar un mapa estático:
fuente
Tienes algunas muy buenas respuestas aquí, pero yo soy para mí, parece un caso de "cuando todo lo que sabes es un martillo" ...
La respuesta más simple de por qué no hay una forma estándar de inicializar un mapa estático, es que no hay una buena razón para usar un mapa estático ...
Un mapa es una estructura diseñada para una búsqueda rápida, de un conjunto desconocido de elementos. Si conoce los elementos de antemano, simplemente use una matriz C. Ingrese los valores de manera ordenada, o ejecute sort sobre ellos, si no puede hacer esto. A continuación, puede obtener el rendimiento de log (n) utilizando las funciones stl :: para enlazar las entradas, lower_bound / upper_bound. Cuando he probado esto anteriormente, normalmente funcionan al menos 4 veces más rápido que un mapa.
Las ventajas son muchas veces ... - rendimiento más rápido (* 4, he medido en muchos tipos de CPU, siempre es alrededor de 4) - depuración más simple. Es más fácil ver qué sucede con un diseño lineal. - Implementaciones triviales de operaciones de copia, en caso de que sea necesario. - No asigna memoria en tiempo de ejecución, por lo que nunca arrojará una excepción. - Es una interfaz estándar, por lo que es muy fácil compartirla, archivos DLL o idiomas, etc.
Podría seguir, pero si quieres más, ¿por qué no miras los numerosos blogs de Stroustrup sobre el tema?
fuente
map
también es una forma útil para representar una función parcial (función en el sentido matemático; pero también, más o menos, en el sentido de la programación). Una matriz no hace eso. No puede, por ejemplo, buscar datos de una matriz utilizando una cadena.