Odpowiedzi:
Za pomocą C ++ 11:
#include <map>
using namespace std;
map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
Za pomocą 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');
Najlepszym sposobem jest użycie funkcji:
#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
zmienne nie będą miały poprawnych wartości w tym „przed głównym konstruktorem czasu wykonywania”, jeśli kompilator zobaczył tylko extern
deklarację, ale nie natrafił jeszcze na rzeczywistą definicję zmiennej .
const map<int,int> m = create_map()
(a więc, zainicjowania stałych elementów klasy na liście inicjalizacji:struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
Stworzenie czegoś podobnego do ulepszenia nie jest skomplikowane. Oto klasa z trzema funkcjami, w tym konstruktorem, do replikacji tego, co zrobiło boost (prawie).
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;
}
};
Stosowanie:
std :: map mymap = create_map <int, int> (1,2) (3,4) (5,6);
Powyższy kod działa najlepiej do inicjowania zmiennych globalnych lub statycznych elementów klasy, które należy zainicjować i nie masz pojęcia, kiedy zostanie najpierw użyty, ale chcesz się upewnić, że wartości są w nim dostępne.
Jeśli powiedzmy, musisz wstawić elementy do istniejącej std :: map ... oto kolejna klasa dla Ciebie.
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());
}
};
Stosowanie:
typedef std::map<int, int> Int2IntMap;
Int2IntMap testMap;
map_add_values<Int2IntMap>(1,2)(3,4)(5,6).to(testMap);
Zobacz to w działaniu z GCC 4.7.2 tutaj: http://ideone.com/3uYJiH
############### WSZYSTKO PONIŻEJ TO JEST OBSOLETE ###################
EDYCJA : Poniższa map_add_values
klasa, która była oryginalnym rozwiązaniem, które zasugerowałem, zawiedzie, jeśli chodzi o GCC 4.5+. Zobacz powyższy kod, aby dowiedzieć się, jak dodać wartości do istniejącej mapy.
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;
}
};
Stosowanie:
std :: map <int, int> moja_mapa; // Później gdzieś wzdłuż kodu map_add_values <int, int> (moja_mapa) (1,2) (3,4) (5,6);
UWAGA: Poprzednio użyłem a operator []
do dodania rzeczywistych wartości. Nie jest to możliwe, jak komentuje dalle.
###################### END OF OBSOLETE SECTION #############################
operator[]
bierze tylko jeden argument.
error: conflicting declaration ‘map_add_values<int, int> my_map’
error: ‘my_map’ has a previous declaration as ‘std::map<int, int> my_map’
Oto inny sposób wykorzystania 2-elementowego konstruktora danych. Do inicjalizacji nie są potrzebne żadne funkcje. Nie ma kodu innej firmy (Boost), żadnych statycznych funkcji lub obiektów, żadnych sztuczek, po prostu prosty C ++:
#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);
Odkąd napisałem tę odpowiedź, C ++ 11 jest niedostępny. Możesz teraz bezpośrednio inicjalizować kontenery STL za pomocą nowej funkcji listy inicjalizacyjnej:
const MyMap myMap = { {"hello", 42}, {"world", 88} };
Na przykład:
const std::map<LogLevel, const char*> g_log_levels_dsc =
{
{ LogLevel::Disabled, "[---]" },
{ LogLevel::Info, "[inf]" },
{ LogLevel::Warning, "[wrn]" },
{ LogLevel::Error, "[err]" },
{ LogLevel::Debug, "[dbg]" }
};
Jeśli map jest członkiem danych klasy, możesz zainicjować go bezpośrednio w nagłówku w następujący sposób (od 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
};
};
Owinąłbym mapę wewnątrz obiektu statycznego i umieściłem kod inicjalizacji mapy w konstruktorze tego obiektu, w ten sposób masz pewność, że mapa zostanie utworzona przed wykonaniem kodu inicjalizacji.
Chciałem po prostu podzielić się czystym obejściem 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;
Możesz spróbować:
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}
zamiast std::pair<int, int>(1, 2)
.
Jest to podobne do PierreBdR
bez kopiowania mapy.
#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);
Jeśli utknąłeś w C ++ 98 i nie chcesz używać boosta, oto rozwiązanie, którego używam, gdy muszę zainicjować mapę statyczną:
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 ] ) ] );
Masz tutaj bardzo dobre odpowiedzi, ale dla mnie wygląda to na przypadek „kiedy wszystko, co wiesz, to młot” ...
Najprostsza odpowiedź na pytanie, dlaczego nie ma standardowego sposobu inicjowania mapy statycznej, nie ma dobrego powodu, aby kiedykolwiek używać mapy statycznej ...
Mapa to struktura zaprojektowana do szybkiego wyszukiwania nieznanego zestawu elementów. Jeśli znasz elementy wcześniej, po prostu użyj tablicy C. Wprowadź wartości w sposób posortowany lub uruchom sortowanie na nich, jeśli nie możesz tego zrobić. Następnie można uzyskać wydajność dziennika (n), używając funkcji stl :: do zapętlania wpisów, dolna_możliwość / górna_możliwość. Kiedy testowałem to wcześniej, zwykle działają one co najmniej 4 razy szybciej niż mapa.
Korzyści są wiele razy ... - szybsza wydajność (* 4, zmierzyłem na wielu typach procesorów, zawsze około 4) - prostsze debugowanie. Po prostu łatwiej jest zobaczyć, co się dzieje z układem liniowym. - Trywialne wdrożenia operacji kopiowania, jeśli okaże się to konieczne. - Nie przydziela pamięci w czasie wykonywania, więc nigdy nie zgłasza wyjątku. - Jest to standardowy interfejs, dzięki czemu można go łatwo udostępniać w różnych bibliotekach DLL, językach itp.
Mógłbym kontynuować, ale jeśli chcesz więcej, spójrz na wiele blogów Stroustrup na ten temat.
map
jest także przydatną formą do reprezentowania funkcji częściowej (funkcja w sensie matematycznym; ale także swego rodzaju w sensie programowania). Tablica tego nie robi. Nie można, powiedzmy, wyszukiwać danych z tablicy za pomocą łańcucha.