vector<string> initialisieren.. -> string==/!=string langsamer als strcmp()??



  • Doch, doch, das geht.

    Die Konstruktorvariante template <class InputIterator> vector (InputIterator first, InputIterator last, const Allocator& = Allocator()) sollte funktionieren, folgendermaßen:

    std::string strarr[] = {"str1", "str2", "str3", "str4"};
    std::vector<std::string> strvec(strarr, strarr + sizeof(strarr) / sizeof(std::string));
    

    Zeiger sind auch Iteratoren, wenn es nach der STL geht.



  • Don Carsto schrieb:

    Ich wollte das std::string Array:

    string sprache[5] = 
    {
    "Deu",
    "Eng",
    "Rus",
    "Pol",
    "Lit"
    };
    

    Als Vector anlegen, ohne weiterhin das string Array zu verwenden.
    (Also nicht, das string Array und den vector anlegen und das string Array dann hineinkopieren)



  • Für sowas kann man schön Boost.Assign nehmen.

    #include <boost/assign/std/vector.hpp>
    
    // ...
    
    vector<string> v;
    v += "Deu", "Pol", "Lit", "...";
    

    Natürlich hast du dann eine zusätzliche Abhängigkeit, die ist in dem Fall aber marginal.



  • Ich dachte, er meinte damit soetwas wie push_back. Noch ein bisschen früh für mich...
    Naja, dann eben Zustimmung für Belli: Geht nicht.



  • Wow, die Lösung mit boost gefällt mir.

    Vielen Dank!!

    Gruß,
    DC



  • Wenn du einen aktuellen Compiler benutzt, der den neuen ( noch nicht verabschiedeten ) Standard unterstützt, kannst du den Vector genau so wie das Array initialisieren. gcc 4.5 oder VisualStudio 2010 unterstützen dies bereits.



  • Hmm, meinst du so?

    vector <string> sprache(5) = 
    {
    "Deu",
    "Eng",
    "Rus",
    "Pol",
    "Lit"
    };
    

    (Mit runden Klammern, oder mit Eckigen?)

    Habe GCC 4.5, aber mit runden Klammern hat es nicht geklappt.

    Gruß,
    DC



  • Hmmm, so geht es...

    vector<string> sprache=
    {
    "Deu",
    "Eng",
    "Ita",
    "Fra",
    "Gri"
    };
    


  • gcc 4.5 oder VisualStudio 2010 unterstützen dies bereits.

    Also VS2010 unterstützt das leider noch nicht, zumindest bekomme ich den Fehler
    error C2552: 'sprache' : non-aggregates cannot be initialized with initializer list



  • Allerdings hat er wohl nun Probleme, den Speicher wieder freizugeben jedenfalls schmeisst er mit nun beim Verlassen der Funktion einen Ausnahmefehler.

    Ich probiere es nun erst einmal mit der boost Lösung.



  • Tja, mit der boost Lösung das gleiche Problem.
    Nach Verlassen der Funktion ein Ausnahmefehler.
    Nur meldet mir der Compiler diesmal, daß er einen nicht-virtuellen Destruktor hat.

    Gehe ich recht in der Annahme, daß der vector am Ende nicht freigegeben werden kann und deswegen diesen Ausnahmefehler erzeugt?


  • Mod

    Don Carsto schrieb:

    Gehe ich recht in der Annahme, daß der vector am Ende nicht freigegeben werden kann und deswegen diesen Ausnahmefehler erzeugt?

    Dies wäre äußerst ungewöhnlich. Zeig mal mehr Code. Das mit dem fehlenden virtuellen Destruktor klingt schon einmal verdächtig. Erbst du etwa von einem STL-Container?



  • Don Carsto schrieb:

    Also, so funktioniert es schonmal nicht. LOL (Wäre auch zu einfach gewesen!!)

    Mit Raten kommst Du in C++ nicht weit. Die Sprache bietet da so einige Irregularitäten. Das kann man sich nicht alles selbst zusammen reimen.



  • Don Carsto schrieb:

    Tja, mit der boost Lösung das gleiche Problem.
    Nach Verlassen der Funktion ein Ausnahmefehler.

    Wahrscheinlich rufst Du irgendwo undefiniertes Verhalten hervor.

    Don Carsto schrieb:

    Nur meldet mir der Compiler diesmal, daß er einen nicht-virtuellen Destruktor hat.

    Wer hat einen nicht-virtuellen Destruktur und warum sollte das hier eine Rolle spielen?

    Don Carsto schrieb:

    Gehe ich recht in der Annahme, daß der vector am Ende nicht freigegeben werden kann und deswegen diesen Ausnahmefehler erzeugt?

    Falsch geraten.

    Versuche das Programm zu verkürzen und vereinfachen und damit den Fehler zu isolieren. Oft findet man so schon den Übeltäter. Wenn Du uns ein kurzes, komplettes Programm zeigen kannst, was sich Deiner Meinung nach ähnlich komisch verhält, dann kann man mehr dazu sagen. Betonung liegt auf "kurz" und "komplett".



  • SeppJ schrieb:

    Dies wäre äußerst ungewöhnlich. Zeig mal mehr Code. Das mit dem fehlenden virtuellen Destruktor klingt schon einmal verdächtig. Erbst du etwa von einem STL-Container?

    Ich habe nun mal das Ganze in eine einfache Consolen Anwendung gepackt. Die Warnungen mit dem non-virtuell-destruktor kommen trotzdem, aber es läuft ohne Ausnahme durch. (Die Warnungen kommen schon,wenn ich nur die boost-include einbinde) Liegt wohl eher an der hohen Warnstufe des Compilers.

    Nun habe ich mal den "fehlerhaften" Code komplett gekürzt und schwupps läuft es durch.
    Da scheint irgendein anderes böses Objekt die Ausnahme zu erzeugen.

    Leider ist der Coee so lang und komplex, daß ein posten nicht viel Sinn macht.

    Da ich nun weiß, daß es nicht am vector selbst liegt, sondern eher an dem chaotischen Drumherum, werde ich das mal entwirren (Schritt für Schritt ausblenden) und die fehlerhafte Stelle suchen.

    Sinn des Ganzen war sowieso zunächst den Code komplett zu Überarbeiten, um unsichere Stellen auszumerzen.

    zu krümelkacker: (Post erst während der Erstellung gelesen)
    Ja, leider kann ich keinen vereinfachten Code posten, der sich ähnlich verhält.
    Und das mit dem Isolieren habe ich gerade in Angriff genommen. Mal sehen.

    Jedenfalls funktioniert die boost-Lösung und auch die GCC 4.5 mit dem noch nicht freigegebenen C++ Standard auch. Der Übeltäter ist irgendwo anders im Code. 👍

    Vielen Dank nochmal für die Unterstützung. Und die Lösung des Problems.

    So.. nun gehts ans Fehlersuchen... 😮

    Gruß,
    DC



  • So, habe die letzten Stunden damit verbracht den Fehler zu suchen.

    Es lag an einem zu kleinen char filestring[40];

    Dieses wurde wohl etwas zu weit (um 3 Zeichen) überschrieben.
    Dadurch wurde die restliche Speicherverwaltung überaus brüchig.
    Hatte sich bisher noch nie bemerkbar gemacht, doch seit ich nun auf std::strings und std::vector umgestellt habe, wurden Ausnahmen geschmissen.

    Eine tickende Zeitbombe....



  • Ich hoffe mal schwer, du hast nun das char[] -Array durch std::string ersetzt und nicht nur um 3 Zeichen vergrössert... 😉

    Wechsle bei der Gelegenheit am besten alle rohen C-Arrays aus (gegen std::tr1::array , boost::array , oder std::array - alles das Gleiche) und ersetze alle Zeiger auf dynamische Arrays durch std::vector .



  • Ja, bin dabei, den kompletten Code zu überarbeiten.
    Das war ja auch Sinn der Übung, daß ich die char Arrays durch std:string ersetzen wollte, a) um zu gucken, ob es dann eine Performance-Erhöhung gibt und b) weil ich std::string sicherer von der Speicherverwaltung halte.
    Nebenher wollte ich dann auch gleich alle mehrdimensionalen char Arrays durch vector<string> ersetzen.

    Habe nun erstmal eine einigermassen lauffähige Version erschaffen, die sich nun genauso verhält wie die Alte, außer, daß es nun 3x-langsamer geworden ist.

    Habe aber auch noch nicht den kompletten Code umgebastelt.
    Sind noch einge Krücken drinne.



  • Don Carsto schrieb:

    Habe nun erstmal eine einigermassen lauffähige Version erschaffen, die sich nun genauso verhält wie die Alte, außer, daß es nun 3x-langsamer geworden ist.

    Sollte nicht sein, wenn man richtig umbaut.

    Natürlich sollte man schon einige Dinge beachten, damit der Vergleich überhaupt gerechtfertigt ist:

    • Ganze Container so selten wie möglich kopieren. Lieber mit Const-Referenzen oder Iteratoren arbeiten.
    • Generell Objekt-Kopien vermeiden durch Einsatz von swap() und Move-Semantik in C++0x.
    • Wenn die Grösse bei std::vector und std::string im Voraus bekannt ist, mit reserve() vorallokieren.
    • Im Release-Modus kompilieren und Debug-Laufzeitumgebung abschalten.
    • Sicherheitsmassnahmen wie Checked-Iterators deaktivieren.


  • So, habe nun die Bremse gefunden.
    Sehr kurios.

    Hatte zunächst nach dem Umstellen auf string und vector folgendes sehr zeitaufwendige Konstrukt von char-Array auf string umgestellt (Dieses wird etwa 26000 mal aufgerufen)
    (Die Schleife selbst ->for(int aa=0;aa<shad_sku.size();aa++)<- ca.65000 mal)

    Hier das Original mit char-Array:

    if (teilupdate==1)
    {
    if (strcmp(test[spalmengel],"0")==0) strcpy(app,"x");
    
    strcpy(bigbuffer,"");
    sprintf(bigbuffer,"%s\t%s\t%s\t%s\t%s\t%s\t%s\t\t\t%s\t%s\t%s\t%s\t%s\t\t\t\t%s\t%s\t%d\t\n",test[spalsku],test[spalautor]
    ,fattitle,test[spalverlag],test[spaljahr],test[spalformat],test[spalpreis],test[spalmengel],test[spalamazustand],fatnote,test[spalkatamazon],test[spalsprache],amaurl,app,7);
    
     for (int aa=0;aa<anzsku;aa++)
      {
       if (strcmp(shad[aa].sku,test[spalsku])==0)
         {
          if((strcmp(shad[aa].anz,test[spalmengel])!=0)||(strcmp(shad[aa].dat,test[spalaenderung])!=0)) {f << bigbuffer;aa=anzsku;flag=1;NR++;}
          else {aa=anzsku;flag=1;}
         }       
      }
    if (flag==0) {f << bigbuffer;NR++;}
    rectx=SUMAKT*balkx/SUMMAX;SUMAKT++;
    }
    

    Laufzeit flotte 16 Sekunden.

    Dann die Abänderung ins std::string + vector:
    bigbuffer ist nun ein stringstream, aber der bremst nicht.

    if (teilupdate==1)
    {
    if (test[spalmengel]=="0") strcpy(app,"x");
    
    bigbuffer << test[spalsku] << "\t" << test[spalautor] << "\t" << fattitle << "\t" << test[spalverlag]
              << "\t" << test[spaljahr] << "\t" << test[spalformat] << "\t" << test[spalpreis] << "\t\t\t"
              << test[spalmengel] << "\t" << test[spalamazustand] << "\t" << fatnote << "\t" << test[spalkatamazon]
              << "\t" << test[spalsprache] << "\t\t\t\t" << amaurl << "\t" << app << "\t" << "7" << "\t\n";
    
    for (int aa=0;aa<shad_sku.size();aa++)
      {
       if (shad_sku.at(aa)==test[spalsku])
         {
          if((shad_anz.at(aa)!=test[spalmengel])||(shad_dat.at(aa)!=test[spalaenderung]))
             {
              f << bigbuffer.str();
              flag=1;
              NR++;
              break;
             }
          else
             {
              flag=1;
              break;
             }
         }
      }
    if (flag==0) {f << bigbuffer.str();NR++;}
    rectx=SUMAKT*balkx/SUMMAX;SUMAKT++;
    }
    

    Laufzeit grobe 60 Sekunden.

    Dann nun wieder abgeändert in:

    if (teilupdate==1)
    {
    if (strcmp(test[spalmengel].c_str(),"0")==0) strcpy(app,"x");
    
    bigbuffer << test[spalsku] << "\t" << test[spalautor] << "\t" << fattitle << "\t" << test[spalverlag]
              << "\t" << test[spaljahr] << "\t" << test[spalformat] << "\t" << test[spalpreis] << "\t\t\t"
              << test[spalmengel] << "\t" << test[spalamazustand] << "\t" << fatnote << "\t" << test[spalkatamazon]
              << "\t" << test[spalsprache] << "\t\t\t\t" << amaurl << "\t" << app << "\t" << "7" << "\t\n";
    
    for (int aa=0;aa<shad_sku.size();aa++)
      {
       if (strcmp(shad_sku.at(aa).c_str(),test[spalsku].c_str())==0)
         {
          if((strcmp(shad_anz.at(aa).c_str(),test[spalmengel].c_str())!=0)||(strcmp(shad_dat.at(aa).c_str(),test[spalaenderung].c_str())!=0))
             {
              f << bigbuffer.str();
              flag=1;
              NR++;
              break;
             }
          else
             {
              flag=1;
              break;
             }
         }
      }
    if (flag==0) {f << bigbuffer.str();NR++;}
    rectx=SUMAKT*balkx/SUMMAX;SUMAKT++;
    }
    

    Also sämtliche string==string und string!=string Vergleiche durch strcmp(x,y)==0/!=0 ersetzt.
    Laufzeit grobe 25 Sekunden.

    .at() und .size() Verzicht führt zu keinerlei Veränderung.

    Warum ist string==string string!=string langsamer als strcmp() ??

    Gibt es da eine Abhilfe?

    Gruß,
    DC


Anmelden zum Antworten