Antworten:
Verwenden von C ++ 11:
#include <map>
using namespace std;
map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
Verwenden von 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');
Der beste Weg ist, eine Funktion zu verwenden:
#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
Variablen haben in diesem "Konstruktor vor der Hauptlaufzeit" nicht die richtigen Werte, wenn der Compiler nur die extern
Deklaration gesehen hat, aber noch nicht auf die eigentliche Variablendefinition gestoßen ist .
const map<int,int> m = create_map()
(und so const-Mitglieder einer Klasse in der Initialisierungsliste zu initialisieren:struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
Es ist kein kompliziertes Problem, etwas Ähnliches zu machen, um es zu verbessern. Hier ist eine Klasse mit nur drei Funktionen, einschließlich des Konstruktors, um zu replizieren, was Boost (fast) bewirkt hat.
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;
}
};
Verwendungszweck:
std :: map mymap = create_map <int, int> (1,2) (3,4) (5,6);
Der obige Code eignet sich am besten für die Initialisierung globaler Variablen oder statischer Elemente einer Klasse, die initialisiert werden muss, und Sie haben keine Ahnung, wann er zuerst verwendet wird, möchten jedoch sicherstellen, dass die Werte darin verfügbar sind.
Wenn Sie sagen, Sie müssen Elemente in eine vorhandene std :: map einfügen ... hier ist eine andere Klasse für Sie.
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());
}
};
Verwendungszweck:
typedef std::map<int, int> Int2IntMap;
Int2IntMap testMap;
map_add_values<Int2IntMap>(1,2)(3,4)(5,6).to(testMap);
Sehen Sie es in Aktion mit GCC 4.7.2 hier: http://ideone.com/3uYJiH
############### ALLES UNTEN IST OBSOLET ##################
BEARBEITEN : Die folgende map_add_values
Klasse, die die ursprüngliche Lösung war, die ich vorgeschlagen hatte, würde in Bezug auf GCC 4.5+ fehlschlagen. Im obigen Code erfahren Sie, wie Sie der vorhandenen Karte Werte hinzufügen .
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;
}
};
Verwendungszweck:
std :: map <int, int> my_map; // Später irgendwo entlang des Codes map_add_values <int, int> (my_map) (1,2) (3,4) (5,6);
HINWEIS: Zuvor habe ich a operator []
zum Hinzufügen der tatsächlichen Werte verwendet. Dies ist nicht möglich, wie von dalle kommentiert.
##################### ENDE DES OBSOLETEN ABSCHNITTS #####################
operator[]
nimmt nur ein einziges 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’
Hier ist eine andere Möglichkeit, den 2-Element-Datenkonstruktor zu verwenden. Zum Initialisieren sind keine Funktionen erforderlich. Es gibt keinen Code von Drittanbietern (Boost), keine statischen Funktionen oder Objekte, keine Tricks, nur einfaches 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);
Seit ich diese Antwort geschrieben habe, ist C ++ 11 raus. Sie können STL-Container jetzt direkt mit der neuen Funktion zur Initialisierungsliste initialisieren:
const MyMap myMap = { {"hello", 42}, {"world", 88} };
Zum Beispiel:
const std::map<LogLevel, const char*> g_log_levels_dsc =
{
{ LogLevel::Disabled, "[---]" },
{ LogLevel::Info, "[inf]" },
{ LogLevel::Warning, "[wrn]" },
{ LogLevel::Error, "[err]" },
{ LogLevel::Debug, "[dbg]" }
};
Wenn map ein Datenelement einer Klasse ist, können Sie es wie folgt direkt im Header initialisieren (seit 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
};
};
Ich würde die Karte in ein statisches Objekt einwickeln und den Karteninitialisierungscode in den Konstruktor dieses Objekts einfügen. Auf diese Weise können Sie sicher sein, dass die Karte erstellt wird, bevor der Initialisierungscode ausgeführt wird.
Ich wollte nur eine reine C ++ 98-Lösung teilen:
#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;
Du kannst es versuchen:
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}
anstelle von verwenden std::pair<int, int>(1, 2)
.
Dies ist ähnlich wie PierreBdR
ohne die Karte zu kopieren.
#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);
Wenn Sie mit C ++ 98 nicht weiterkommen und Boost nicht verwenden möchten, gibt es hier die Lösung, die ich verwende, wenn ich eine statische Map initialisieren muss:
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 ] ) ] );
Sie haben hier einige sehr gute Antworten, aber ich bin für mich, es sieht aus wie ein Fall von "wenn alles, was Sie wissen, ein Hammer ist" ...
Die einfachste Antwort darauf, warum es keine Standardmethode zum Initialisieren einer statischen Karte gibt, ist, dass es keinen guten Grund gibt, jemals eine statische Karte zu verwenden ...
Eine Karte ist eine Struktur, die für die schnelle Suche nach einem unbekannten Satz von Elementen entwickelt wurde. Wenn Sie die Elemente vorher kennen, verwenden Sie einfach ein C-Array. Geben Sie die Werte sortiert ein oder sortieren Sie sie, wenn Sie dies nicht können. Sie können dann die Leistung von log (n) erhalten, indem Sie die stl :: -Funktionen verwenden, um Einträge (lower_bound / obere_bound) zu schleifen. Wenn ich dies zuvor getestet habe, arbeiten sie normalerweise mindestens viermal schneller als eine Karte.
Die Vorteile sind vielfältig ... - schnellere Leistung (* 4, ich habe an vielen CPU-Typen gemessen, es sind immer etwa 4) - einfacheres Debuggen. Mit einem linearen Layout ist es einfacher zu sehen, was los ist. - Triviale Implementierungen von Kopiervorgängen, falls dies erforderlich werden sollte. - Es weist zur Laufzeit keinen Speicher zu und löst daher niemals eine Ausnahme aus. - Es ist eine Standardschnittstelle und daher sehr einfach für DLLs, Sprachen usw. freizugeben.
Ich könnte weitermachen, aber wenn Sie mehr wollen, schauen Sie sich doch die vielen Blogs von Stroustrup zu diesem Thema an.
map
ist auch eine nützliche Form zur Darstellung einer Teilfunktion (Funktion im mathematischen Sinne; aber auch im Programmiersinn). Ein Array macht das nicht. Sie können beispielsweise keine Daten aus einem Array mithilfe einer Zeichenfolge suchen.