Was ist der richtige Weg, um eine statische Karte zu initialisieren? Benötigen wir eine statische Funktion, die sie initialisiert?
447
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:
quelle
extern
Variablen haben in diesem "Konstruktor vor der Hauptlaufzeit" nicht die richtigen Werte, wenn der Compiler nur dieextern
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.
Verwendungszweck:
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.
Verwendungszweck:
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 .Verwendungszweck:
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 #####################
quelle
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 ++:
Seit ich diese Antwort geschrieben habe, ist C ++ 11 raus. Sie können STL-Container jetzt direkt mit der neuen Funktion zur Initialisierungsliste initialisieren:
quelle
Zum Beispiel:
Wenn map ein Datenelement einer Klasse ist, können Sie es wie folgt direkt im Header initialisieren (seit C ++ 17):
quelle
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.
quelle
Ich wollte nur eine reine C ++ 98-Lösung teilen:
quelle
Du kannst es versuchen:
quelle
{1, 2}
anstelle von verwendenstd::pair<int, int>(1, 2)
.Dies ist ähnlich wie
PierreBdR
ohne die Karte zu kopieren.quelle
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:
quelle
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.
quelle
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.