STL - Fragen zu vector



  • Hallo zusammen

    Ich arbeite gerade viel mit Vectoren anstatt mit arrays. Nun wollte ich einen Bereich aus einem Array einem Vektor zuweisen. Muss ich das mit einer Schleife machen und jedes einzelne Element mit push_back in den vector stecken oder geht das auch schneller? Also irgendwas mit insert(Bereich von bis). Wenn es sowas gibt ist das dann schneller als push_back oder genauso langsam?

    Effizienz: Sind vectoren effizienter als arrays oder ist es besser arrays zu nehmen. Da ich ein grosses Programm laufen habe das hauptsaechlich zur Optimierung dient und daher schnell laufen sollte waere das wichtig fuer mich.

    Vielen Dank fuer jede Hilfe



  • Das musst du in einer Schleife machen.
    std::vector ist eigentlich nur ein schlanker Wrapper für ein herkömmliches dynamisches Array (also Typ*). Daher sollte es laut Standard mindestens genauso schnell sein.



  • Du kannst assign oder insert nehmen. Die Methoden für "Range"-Zugriffe sollten immer handgeschriebenen Schleifen bevorzugt werden. (Siehe Effective-STL von Scott Meyers)

    Beispiel:

    std::vector<int> klaus;
    int array[20] = {1, 2, 3};
    
    klaus.insert( array, array+20);
    klaus.assign( array, array+20);
    

    Dem Vektor wäre es in diesem Beispiel möglich zu erkennen (durch Spezialisierung), wieviele Elemente eingefügt werden und könnte sich somit vorher einmal die passende Größe reservieren, anstatt ständig zu wachsen. Dass das für das Einfügen aus einer linearen Liste (z.B. std::list) nicht funktionieren kann, ist hoffentlich klar (die Länge einer linearen Liste zu ermitteln benötigt lineare Zeit, was nicht mehr zu rechtfertigen wäre, da man eh schon einmal über jedes Element iteriert).

    Falls du mehr Wissen hast als der Bauer der STL über deine Implementation haben kann (z.B. Länge der linearen Liste), so kannst du vor dem Einfügen ein händisches reserve auf den Vektor machen und somit ständige Neuallokationen verhindern.

    Solange man Vektoren nicht grob fahrlässig benutzt, sind sie in etwa genausoschnell wie blanke arrays.

    Immerhin wächst der Vektor bei Vergrößerung nicht linear, sonder polynomial (genauer: 2*size), was die Performance-Einbußen für Reallokation in Grenzen hält.



  • Zum einfügen kannst du auch insert nehmen:

    char array[100];
    vector<char> vec;
    vec.insert(vec.start(),array+10,array+20);//fügt den 10. bis 19. Buchstaben aus dem Array in den Vektor ein
    

    Achja, falls du vorhandene Vektor-Elemente überschreiben willst, nimm lieber std::copy()



  • Ui, o.k., da habe ich ja ne ganze Menge Moeglichkeiten. Ich glaube ich sollte mir wirklich mal das Buch besorgen.

    Jetzt bleibt trotzdem die Frage welche der Moeglichkeiten die effektivste ist, wenn ich die Laenge meines 3 dimensionalen arrays kenne und einfach die erste Dimension einfuegen will, also von 0 - N (wenn das array N x 3 ist). Kann ich da einfach die Methode nehmen die mir am besten gefaellt oder gibts zwischen den einzelnen Methoden schon nochmal Laufzeitunterschiede bzw Speicherplatzanspruch?



  • insert fügt an, assign setzt den Inhalt neu. 😉

    Es gibt übrigens auch Range-Konstruktoren:

    int array[20] = {5, 6, 7};
    std::vector<int> harry( array, array+20);
    

    Vielleicht interessant für dich zu wissen: Wird ein Vektor kleiner, so gibt er seinen Speicher, den er schon besitzt, nicht wieder frei. Willst du das aber, so musst du soetwas in der Art machen:

    std::vector<int> klaus( 100U, 0); // 100 mal 0 einfügen
    klaus.clear(); // Inhalt ist weg, Speicher bleibt aber belegt
    {
      std::vector<int> harry; // Leerer Vektor ohne Speicher
      harry.swap( klaus); // Inhalte, d.h. Speicher tauschen
    } // jetzt wird harry zerstört, und damit auch der ursprüngliche Speicher von klaus. klaus besitzt jetzt keinen Speicher mehr
    

    Zu solchen Fragen kann ich dir wirklich nur das Buch Effective STL nahelegen. 😉



  • O.k., ich sehs ja ein, ich werde mir das Buch besorgen ;-). Wahrscheinlich habe ich in meinem Programm noch einige Schnitzer was STL anbelangt.

    Vielen Dank fuer die schnellen Antworten. Einen schoenen Tag noch



  • Sorry, jetzt ist doch noch ein Problem aufgetreten. Ich wollte das mit dem Konstruktor ausprobieren. Allerdings bekomme ich folgende Fehlermeldung:

    error C2668: 'std::_Iter_cat' : ambiguous call to overloaded function

    mein Aufruf sieht folgendermassen aus:
    vector<double> vAlpha(alpha[taud*N],alpha[taud*N]+N);

    Geht das doch nicht, wenn ich fuer jede Dimension meines Arrays einen Vector anlegen will?



  • Zeig mal die Definition von taud.

    Vermutlich musst du aber

    vector<double> vAlpha(&alpha[taud*N],&alpha[taud*N]+N);
    

    schreiben.

    Der Grund dafür ist: Ein Array (bei dir alpha) konvertiert implizit in einen Pointer auf das erste Element (und eignet sich deshalb für einen Range-Konstruktor, da ein Zeiger als Random-Access-Iterator behandelt wird). Der []-Zugriff auf ein Array liefert aber eine Referenz an die entsprechende Stelle und keinen Pointer. Deshalb reicht es wohl vermutlich auch, den Adressoperator anzuwenden.

    Btw, mit [cpp]-Tags sieht das viel schicker und leserlicher aus 🙂



  • Mit dem Adressoperator funktionierts 🙂

    Was sind denn [cpp]-flags?



  • Ups, meinte natuerlich [cpp]-Tags



  • Nicht flags sondern Tags 😉

    Wenn du vor und hinter C++ Code das hier schreibst:

    Irgendwelcher C/C++ Code
    

    , dann wird der schick eingefärbt und ist viel besser lesbar. Und auch die Formatierung bleibt erhalten.

    und
    

    nennt man Tags 😉 Die werden normalerweise automatisch vom Board umgesetzt. Nur jetzt bei mir gerade nicht, weil ich bei "BBCode in diesem Beitrag deaktivieren" ein Häkchen gesetzt habe. Guck dir mal andere Beiträge im Forum an, dann siehst du es ganz schnell.



  • Ah jetzt verstehe ich. Cool, danke, wieder was gelernt :-).


Anmelden zum Antworten