std::map build - Warum dauert das so lange?
-
Mr.Long schrieb:
Und bitte übergebe Referenzen.
Wo meinst du jetzt, im Konstruktor? Die strings müssen da doch eh kopiert werden, ist dass da nicht egal?
Hab übrigens ein neues Problem mit der Array Technik. Und zwar ist folgendes extrem nervig:
struct Data { Data() {}; Data(int number_, std::string text1_, std::string text2_) : number(number_), text1(text1_), text2(text2_) {}; std::string text1; std::string text2; int number; }; // Daten Array mit den 4000 Einträgen const int DATA_SIZE = 2; Data const data_array[] = { Data(0, "kurzer test string", "langer test string"), Data(0, "kurzer test string", "langer test string") }; int _tmain(int argc, _TCHAR* argv[]) { std::map<std::string, Data> my_map; for (unsigned int i = 0; i < DATA_SIZE; i++) { my_map["?"] = data_array[i]; // <- Wie komm ich jetzt hier an den zugehörigen key? } return 0; }
Zwar kann ich meine Daten jetzt in das const array reinschmeissen, allerdings hab ich dann ja nicht den benötigten key für die map zur Verfügung, da der Schlüssel nicht in der struct Data gespeichert werden soll.
Einzige Lösung die mir bis jetzt einfällt um das zu lösen wäre ein zweites Array mit den keys mitzuschleifen. Das ist aber extrem nervig, da die Übersicht dann noch mehr leidet. Vor allem wenn man dann mal eine Zeile löschen/hinzufügen will muss man dann genau aufpassen dass man das alles manuell richtig macht.
Daher ist ein zweites array wohl keine gute Lösung. Wie könnte man das sonst machen? Muss ja irgendwie möglich sein eine map vernünftig und ohne massiven manuellen Aufwand zu initialisieren?
Da hätte ich auch gleich noch eine Frage. Die lange Build-Zeit bei Initialisierung ohne array resultiert wohl aus den 4000 Konstruktor-Aufrufen in der Funktion. Wenn ich keine eigene Datenstruktur einfüge sondern direkt strings ist die Build-Zeit sehr kurz - was macht die std::string Klasse hier anders dass deren Konstruktoren soviel effektiver gebuildet werden können?
-
std::pair<std::string, Data> const data_array[] = { std::pair<std::string, Data>("key1", Data(0, "kurzer test string", "langer test string")), std::pair<std::string, Data>("key2", Data(0, "kurzer test string", "langer test string")), // ... }; size_t const data_size = sizeof(data_array)/sizeof(data_array[0]); int _tmain(int argc, _TCHAR* argv[]) { std::map<std::string, Data> my_map(&data_array[0], &data_array[data_size]); // <- Das wäre eine Möglichkeit return 0; } // oder gleich so -----------------------V std::map<std::string, Data> const my_global_map(&data_array[0], &data_array[data_size]);
-
Und warum soll das schneller sein. Ich finde es aleine schon problematisch wieviele Allocationen hier durchgeführt werden müssen.
Bei Programmstart, dann nochmal muss das ganze Zeugs kopiert werden...Nimm z.B. Smart-Pointer und lass die Daten nur einmal erzeugen, was natürlich einen weitere indirekten Zugriff bedeutet, aber damit würden die Objekte nicht kopiert. Oder wenn das statisch ist arbeite mit const Zeigern.
-
Wie oft ändern sich denn die Einträge in die Maß?
Wenn das relativ statisch ist, dann könnte man das Befüllen der Map auch in eine eigene Objektdatei packen und die nicht bei jeder kleinen Änderung am eigentlichen Programm neu kompiliert werden müsste.
-
Martin Richter schrieb:
Und warum soll das schneller sein.
Was ist in letzter Zeit immer mit den unpassenden "warum soll das {xxx} sein" Fragen
Ich hab' nie behauptet dass es "schneller" sein soll (schneller als was übrigens?).Die Frage war
happystudent schrieb:
Zwar kann ich meine Daten jetzt in das const array reinschmeissen, allerdings hab ich dann ja nicht den benötigten key für die map zur Verfügung, da der Schlüssel nicht in der struct Data gespeichert werden soll.
Einzige Lösung die mir bis jetzt einfällt um das zu lösen wäre ein zweites Array mit den keys mitzuschleifen. Das ist aber extrem nervig, da die Übersicht dann noch mehr leidet. Vor allem wenn man dann mal eine Zeile löschen/hinzufügen will muss man dann genau aufpassen dass man das alles manuell richtig macht.
Daher ist ein zweites array wohl keine gute Lösung. Wie könnte man das sonst machen? Muss ja irgendwie möglich sein eine map vernünftig und ohne massiven manuellen Aufwand zu initialisieren?
-
hustbaer schrieb:
std::map<std::string, Data> my_map(&data_array[0], &data_array[data_size]); // <- Das wäre eine Möglichkeit
Ah, das ist schon viel besser
Morle schrieb:
Wie oft ändern sich denn die Einträge in die Maß?
Wenn das relativ statisch ist, dann könnte man das Befüllen der Map auch in eine eigene Objektdatei packen und die nicht bei jeder kleinen Änderung am eigentlichen Programm neu kompiliert werden müsste.
Die Einträge ändern sich eigentlich ziemlich selten. Macht es dann einen Unterschied ob man eine fertig kompilierte .cpp Datei hat (die ja beim kompilieren dann auch nicht mehr angefasst wird) oder eine eigene Objektdatei?
Martin Richter schrieb:
Und warum soll das schneller sein. Ich finde es aleine schon problematisch wieviele Allocationen hier durchgeführt werden müssen.
Bei Programmstart, dann nochmal muss das ganze Zeugs kopiert werden...Ist der Compiler nicht schlau genug das selbst zu checken? Weil das Daten-Array würde ich nur lokal in der Funktion befüllen, die dann auch die map befüllt.
EDIT: Hm, nach dem Verlagern der Initialisierung in eine eigene Funktion erhalte ich einen Stack-Overflow... Wenn ich das array global deklariere allerdings nicht. Wie kann das jetzt sein, ich will das Daten-Array ja nicht die Ganze Zeit im Speicher mitschleifen, daher würde ich es gerne lokal in einer extra Funktion haben dass es nach befüllen der map wieder freigegeben werden kann...
-
Dein lokaler Heap ist eben begrenzt. Und Du schleppst dennoch den Code und den Speicher mit Dir rum. Spätestens in der EXE...
-
Ok, und was mache dann jetzt am besten? Kann ja nicht sein dass es so kompliziert ist eine map effizient zu befüllen...
-
Nimm einen Statischen Array als POD.
Verwende in der MAP nur const Zeiger auf diesen Array.
-
...oder lies den Kram aus einer Datei ein. Kann ja nicht sein, dass diese 4000 Key-Value-Pairs so statisch sind, dass sie unbedingt in der exe sein müssen.
MfG SideWinder