Respuestas:
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:
#include <map>
using namespace std;
map<int,int> create_map()
{
map<int,int> m;
m[1] = 2;
m[3] = 4;
m[5] = 6;
return m;
}
map<int,int> m = create_map();
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 la extern
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).
template <typename T, typename U>
class create_map
{
private:
std::map<T, U> m_map;
public:
create_map(const T& key, const U& val)
{
m_map[key] = val;
}
create_map<T, U>& operator()(const T& key, const U& val)
{
m_map[key] = val;
return *this;
}
operator std::map<T, U>()
{
return m_map;
}
};
Uso:
std :: map mymap = create_map <int, int> (1,2) (3,4) (5,6);
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.
template <typename MapType>
class map_add_values {
private:
MapType mMap;
public:
typedef typename MapType::key_type KeyType;
typedef typename MapType::mapped_type MappedType;
map_add_values(const KeyType& key, const MappedType& val)
{
mMap[key] = val;
}
map_add_values& operator()(const KeyType& key, const MappedType& val) {
mMap[key] = val;
return *this;
}
void to (MapType& map) {
map.insert(mMap.begin(), mMap.end());
}
};
Uso:
typedef std::map<int, int> Int2IntMap;
Int2IntMap testMap;
map_add_values<Int2IntMap>(1,2)(3,4)(5,6).to(testMap);
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.
template<typename T, typename U>
class map_add_values
{
private:
std::map<T,U>& m_map;
public:
map_add_values(std::map<T, U>& _map):m_map(_map){}
map_add_values& operator()(const T& _key, const U& _val)
{
m_map[key] = val;
return *this;
}
};
Uso:
std :: map <int, int> my_map; // Más tarde en algún lugar del código map_add_values <int, int> (my_map) (1,2) (3,4) (5,6);
NOTA: Anteriormente utilicé un operator []
para agregar los valores reales. Esto no es posible como lo comentó dalle.
##################### FIN DE LA SECCIÓN OBSOLETA #####################
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:
#include <map>
#include <string>
typedef std::map<std::string, int> MyMap;
const MyMap::value_type rawData[] = {
MyMap::value_type("hello", 42),
MyMap::value_type("world", 88),
};
const int numElems = sizeof rawData / sizeof rawData[0];
MyMap myMap(rawData, rawData + numElems);
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:
const MyMap myMap = { {"hello", 42}, {"world", 88} };
Por ejemplo:
const std::map<LogLevel, const char*> g_log_levels_dsc =
{
{ LogLevel::Disabled, "[---]" },
{ LogLevel::Info, "[inf]" },
{ LogLevel::Warning, "[wrn]" },
{ LogLevel::Error, "[err]" },
{ LogLevel::Debug, "[dbg]" }
};
Si map es un miembro de datos de una clase, puede inicializarlo directamente en el encabezado de la siguiente manera (desde C ++ 17):
// Example
template<>
class StringConverter<CacheMode> final
{
public:
static auto convert(CacheMode mode) -> const std::string&
{
// validate...
return s_modes.at(mode);
}
private:
static inline const std::map<CacheMode, std::string> s_modes =
{
{ CacheMode::All, "All" },
{ CacheMode::Selective, "Selective" },
{ CacheMode::None, "None" }
// etc
};
};
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.
Solo quería compartir una solución pura de C ++ 98:
#include <map>
std::map<std::string, std::string> aka;
struct akaInit
{
akaInit()
{
aka[ "George" ] = "John";
aka[ "Joe" ] = "Al";
aka[ "Phil" ] = "Sue";
aka[ "Smitty" ] = "Yando";
}
} AkaInit;
Puedes probar:
std::map <int, int> mymap =
{
std::pair <int, int> (1, 1),
std::pair <int, int> (2, 2),
std::pair <int, int> (2, 2)
};
{1, 2}
lugar de std::pair<int, int>(1, 2)
.
Esto es similar a PierreBdR
, sin copiar el mapa.
#include <map>
using namespace std;
bool create_map(map<int,int> &m)
{
m[1] = 2;
m[3] = 4;
m[5] = 6;
return true;
}
static map<int,int> m;
static bool _dummy = create_map (m);
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:
typedef std::pair< int, char > elemPair_t;
elemPair_t elemPairs[] =
{
elemPair_t( 1, 'a'),
elemPair_t( 3, 'b' ),
elemPair_t( 5, 'c' ),
elemPair_t( 7, 'd' )
};
const std::map< int, char > myMap( &elemPairs[ 0 ], &elemPairs[ sizeof( elemPairs ) / sizeof( elemPairs[ 0 ] ) ] );
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?
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.