532 Stimmen

Initialisierung einer statischen std::map<int, int> in C++

Wie kann man eine statische Karte richtig initialisieren? Brauchen wir eine statische Funktion, die sie initialisiert?

734voto

Ferruccio Punkte 96076

C++11 verwenden:

#include <map>
using namespace std;

map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};

Verwendung von Boost.Zuweisen :

#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');

139voto

PierreBdR Punkte 40155

Der beste Weg ist die Verwendung einer Funktion:

#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();

117voto

Vite Falcon Punkte 6425

Es ist gar nicht so schwierig, etwas Ähnliches wie Boost zu machen. Hier ist eine Klasse mit nur drei Funktionen, einschließlich des Konstruktors, um zu replizieren, was boost (fast) getan 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;
    }
};

Verwendung:

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 Mitglieder einer Klasse, die initialisiert werden muss und von der man nicht weiß, wann sie zum ersten Mal verwendet wird, aber man möchte sicherstellen, dass die Werte darin verfügbar sind.

Wenn Sie z.B. Elemente in eine bestehende std::map einfügen müssen... hier ist eine weitere 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());
    }
};

Verwendung:

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 DARUNTER IST VERALTET #################

EDIT : Die map_add_values Klasse unten, die die ursprüngliche Lösung, die ich vorgeschlagen hatte, würde fehlschlagen, wenn es zu GCC 4.5+ kommt. Bitte sehen Sie sich den Code oben an, um zu erfahren, wie man hinzufügen. Werte zur bestehenden Karte.

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;
    }
};

Verwendung:

std::map<int, int> my\_map;
// Later somewhere along the code
map\_add\_values<int,int>(my\_map)(1,2)(3,4)(5,6);

HINWEIS: Zuvor habe ich eine operator [] für die Addition der tatsächlichen Werte. Dies ist, wie von dalle kommentiert, nicht möglich.

##################### ENDE DES ÜBERHOLTEN ABSCHNITTS #####################

46voto

Brian Neal Punkte 30564

Hier ist eine weitere Möglichkeit, die den 2-Elemente-Datenkonstruktor verwendet. Es werden keine Funktionen zur Initialisierung benötigt. 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 erschienen. Sie können jetzt STL-Container direkt initialisieren, indem Sie die neue Funktion der Initialisierungsliste verwenden:

const MyMap myMap = { {"hello", 42}, {"world", 88} };

37voto

isnullxbh Punkte 687

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 direkt im Header auf folgende Weise 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
        };
};

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X