std::map< int, std::string[2][4] > geht nicht?



  • Mein Compiler sagt mir zu folgendem:

    std::map< int, std::string[2][4] > m_Map;
    
    //...
    
    int val = 4;
    
    if( m_LanguageMap.find( 4 ) == m_Map.end() )
    {
    	std::string temp_array[2][4];
    
    	m_Map.insert( std::make_pair( 4, temp_array ) );
    }
    
    There are no conversions to array types, although there are conversions to references or pointers to arrays
    

    Lässt sich dieses Problem nur über einen Pointer auf ein Array lösen?

    Wie würde es mit folgendem aussehen:

    std::vector< std::string[2][4] >
    


  • So geht's:

    std::vector<std::vector<std::string> > vec;
    

    Oder übertragen auf das Beispiel mit der std::map

    std::map< int, std::vector<std::vector<std::string> > > m_Map;
    


  • Das es so geht ist mir schon klar.

    Allerdings ist das nicht gewünscht.
    Die map kann 100te keys haben.
    Die größe des Arrays das als value verwendet werden soll ist immer 2x4.
    Für jedes dieser Arrays einen vector zu nehmen würde einen unnötigen Overhead erzeugen.



  • std::map< int, char[2][4][50] > m_Map;
    

    ^^



  • haha 🙄



  • Na wenn das so ist, dann löse es doch mit einem Zeiger auf ein Array, mit recht viel weniger Overhead als bei der von mir genannten Lösung wird es nicht gehen.



  • struct StrArray
    {
    std::string strings[2][4];
    }

    std::map< int, StrArray > m_Map;

    Das tut und ein paar hundert structs sollten doch bei weitem weniger Overhead produzieren als ein paar hundert std::vector oder irre ich da?



  • Was für'n Overhead erwartest Du denn von den Vektoren? Der Zugriff per operator [] oder Iteratoren sollte genau null Overhead haben. Und Du solltest Dich fragen, ob die paar extra Bytes, die benötigt werden, um die Größe zu speichern, hier ins Gewicht fallen (wobei das bei so kleinen Arrays ja durchaus nen substanzieller Anteil ist …).

    Abgesehen davon, das Overhead der Struktur sollte auch gleich null sein.



  • Um Geschwindigkeit hab ich mir auch niemals Gedanken gemacht, mir ging es um Speicher.

    Laut sizeof braucht ein einzelner std::vector schonmal 20 Bytes unabhängig vom Inhalt.
    Bei folgender Lösung:

    std::map< int, std::vector< std::vector< std::string > > >
    

    würden die std::vector nach meiner Rechnung bei 1000 Keys 1000*1*4*20 Bytes brauchen. Das sind immerhin schon 78 kb.

    struct braucht hingegen laut sizeof lediglich den Platz der zum Speichern der gekapselten Datentypen benötigt wird, also fallen diese 78 kb weg oder verstehe ich da was falsch?

    78 kb an sich mögen vielleicht nicht viel sein, allerdings wird der Code in einem Programm verwendet welches an anderen Stellen sehr viel Speicher braucht, von daher finde ich es durchaus angemessen um jedes Byte zu kämpfen.



  • stein schrieb:

    78 kb an sich mögen vielleicht nicht viel sein, allerdings wird der Code in einem Programm verwendet welches an anderen Stellen sehr viel Speicher braucht, von daher finde ich es durchaus angemessen um jedes Byte zu kämpfen.

    wie viel ist denn "sehr viel"?



  • stein schrieb:

    Um Geschwindigkeit hab ich mir auch niemals Gedanken gemacht, mir ging es um Speicher.

    Gut, in dem Fall ist der von Dir vorgeschlagene Weg über die 'struct' wohl wirklich der richtige. Ich wollte nur explizit auf die Kosten (bzw. Abwesenheit davon) hinweisen, damit Du keine vorschnelle, uninformierte Entscheidung triffst.

    Bei vielen Daten könnte das Speicher-Overhead übrigens auch Performance-technisch durchaus ins Gewicht fallen, weil Du Dir dadurch eventuell Cache-Misses einhandelst.



  • Wenn ich mir die Spec so anschaue dann in manchen Fällen 300 MB aufwärts.

    Ich weiß zwar ganz genau was jetzt gleich kommt:
    "Da machen die paar kb den Hahn aber auch nicht mehr fett...bla bla bla"

    aber wenn man nicht schon zu Beginn des Projekts auf solche Sachen geachtet hätte würde man selbst mit der doppelten Speichermenge nicht auskommen.

    Der Punkt ist einfach dass es sich hierbei um ein riesiges Projekt handelt an dem mehrere Entwickler parallel arbeiten und ich hab mich schon oft genug darüber aufgeregt wenn ich irgendeinen Murx richten musste nur weil einer sich nicht die Arbeit gemacht hat nach einer effizienten Lösung zu suchen.


  • Mod

    Normale Arrays können weder kopiert noch zugewiesen werden, damit sind sie nicht als Elemente von Standardcontainern geeignet. Das Verpacken in einer Klasse ist dabei daher ein Standardverfahren (auch in C im Übrigen). Sinnvoll ist hier der Einsatz von std::tr1::aray (hilfsweise boost::tr1::array) - das wurde gerade für solche Fälle geschaffen.


Anmelden zum Antworten