Anzeige:
Ergebnis 1 bis 6 von 6

Thema: [C++] vector::size und ::capacity?

  1. #1
    Registrierter Benutzer
    Registriert seit
    31.01.2007
    Beiträge
    18

    [C++] vector::size und ::capacity?

    Hallo,

    ich gruebel gerade ueber den Unterschied zwischen size und capacity. Aus den Tutorials und anderen Quellen habe ich (vermeintlich) verstanden, dass size nur die Anzahl der Elemente aber capacity die moegliche Anzahl von Elementen zurueck gibt. Ist das soweit korrekt?

    Vermutlich nicht, denn wenn ich
    Code:
    int main(int argc, char **argv)
    {
      vector<int> ivec;
      
      cout << "empty?: " << ivec.empty() << endl;
      cout << "capacity: " << ivec.capacity() << endl;
      cout << "size: " << ivec.size() << endl << endl;
      
      ivec.reserve(20);
      cout << "after reserve:" << endl;
      cout << "empty?: " << ivec.empty() << endl;
      cout << "capacity: " << ivec.capacity() << endl;
      cout << "size: " << ivec.size() << endl << endl;
      
      for(unsigned int i = 0; i < ivec.capacity()/2; ++i) 
      {
        ivec[i] = i;
      }
      
      cout << "after ini:" << endl;
      cout << "empty?: " << ivec.empty() << endl;
      cout << "capacity: " << ivec.capacity() << endl;
      cout << "size: " << ivec.size() << endl;
      for(unsigned int i = 0; i < ivec.capacity(); ++i) 
      {
        cout << ivec[i] << ", ";
      }
    
      return 0;
    }
    laufen lasse, bekomme ich:
    Code:
    empty?: 1
    capacity: 0
    size: 0
    
    after reserve:
    empty?: 1
    capacity: 20
    size: 0
    
    after ini:
    empty?: 1
    capacity: 20
    size: 0
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    Die ersten beiden Ausgabebloecke sind klar, doch beim 3. Block sollte sich dann doch mal was aendern. Schliesslich wurde der Vektor mit Elementen gefuellt.

    Was mache ich falsch???

    Danke im Voraus,
    HarryKane

    EDIT: Ahh, es gibt neben vector::reserve auch noch vector::resize (das hab ich voellig uebersehen). Trozdem wundert es mich ein wenig, warum nach Eingabe meiner Elemente der Vektor immer noch leer sein sollte. Erst wenn ich vorher mit resize eine Groesse definiert habe, ist er nicht mehr leer. Das finde ich irgendwie sehr merkwuerdig. Wozu benoetigt man dann ueberhaupt noch reserve, wenn doch auch resize die Kapazitaet erhoeht *gruebel*
    Geändert von HarryKane (24-06-2008 um 10:45 Uhr)

  2. #2
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Also:

    reserve() definiert die Mindestkapazität des Vektors
    resize() definiert die aktuelle Grösse des Vektors

    Bei mir, wenn ich das reserve() durch ein resize() ersetze erhalte ich folgendes:
    Code:
    peschmae@sid:/tmp$ ./test
    empty?: 1
    capacity: 0
    size: 0
    
    after reserve:
    empty?: 0
    capacity: 20
    size: 20
    
    after ini:
    empty?: 0
    capacity: 20
    size: 20
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, peschmae@sid:/tmp$
    Also alles wies sein sollte.

    Wobei deine Verwendung von resize() hier eher etwas unglücklich ist, weisst du doch nachher nicht mehr welche Elemente des Vektors jetzt nützliche Informationen enthalten und welche nur durch das resize() entstanden sind...

    (Wobei dir das wohl egal ist weil du nur wissen willst was genau was bewirkt oder wie?)

    Also eigentlich besser sowas machen in der Praxis:
    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main(int argc, char **argv)
    {
      vector<int> ivec;
    
      cout << "after reserve:" << endl;
      cout << "empty?: " << ivec.empty() << endl;
      cout << "capacity: " << ivec.capacity() << endl;
      cout << "size: " << ivec.size() << endl << endl;
    
      for(unsigned int i = 0; i < 20; ++i)
      {
            ivec.push_back(i);
      }
    
      cout << "after ini:" << endl;
      cout << "empty?: " << ivec.empty() << endl;
      cout << "capacity: " << ivec.capacity() << endl;
      cout << "size: " << ivec.size() << endl;
      for(unsigned int i = 0; i < ivec.size(); ++i)
      {
        cout << ivec[i] << ", ";
      }
    
      return 0;
    }

    Wie du hier siehst ist capacity() > size(); d.h. es ist erstmal für mehr Elemente Speicher reserviert als du eigentlich belegt hast.

    MfG Peschmä
    Geändert von peschmae (24-06-2008 um 19:09 Uhr)
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  3. #3
    Registrierter Benutzer
    Registriert seit
    31.01.2007
    Beiträge
    18
    Zitat Zitat von peschmae Beitrag anzeigen
    Also:

    reserve() definiert die Mindestkapazität des Vektors
    resize() definiert die aktuelle Grösse des Vektors

    Wobei deine Verwendung von resize() hier eher etwas unglücklich ist, weisst du doch nachher nicht mehr welche Elemente des Vektors jetzt nützliche Informationen enthalten und welche nur durch das resize() entstanden sind...

    (Wobei dir das wohl egal ist weil du nur wissen willst was genau was bewirkt oder wie?)
    Ja genau, ich wollte erstmal gucken was was macht.

    Mir ist letztendlich nur noch nicht klar wozu es reserve dann überhaupt gibt.
    Egal ob ich mit resize oder push_back arbeite, die Kapazität wird doch eh automatisch angepasst.

    Also eigentlich besser sowas machen in der Praxis:
    [...]
    Hmm, ich fands irgendwie sinnvoller erstmal den Vektor zu erschaffen (wie ich ihn brauche) und dann mit Werten zu besetzen, als immer ein neues Element hinten dran zu pappen.

    Das macht natürlich nur dann sinn, wenn man gerade den Vektor erschafft. Mitten im Programm ist dann definitiv push_back die bessere Variante.

  4. #4
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Zitat Zitat von HarryKane Beitrag anzeigen
    Mir ist letztendlich nur noch nicht klar wozu es reserve dann überhaupt gibt.
    Achso. Ich versuchs nochmal (hoffentlich erzähle ich bei all dem Erklären von Zeugs das ich in letzter Zeit nie wirklich benutzt habe nicht allzuviel Blödsinn):
    "Mindestgrösse" war wohl etwas ungeschickt ausgedrückt.

    reserve betrifft das Backend des Vektors. Im Hintegrund hat der ein Array, das ist "capacity()" lang. Das braucht dich erst mal nicht kümmern, denn du arbeitest mit:

    resize/push_back/at()/[] - die sind das Frontend vom Vektor. Von genanntem Array benutzt du "size()" Elemente.

    D.h. wenn du vorher weisst dass du 20 Elemente benötigst, kannst du ein resize(20) machen - das sagt dann auch gleich dem Backend dass capacity() mindestens 20 sein muss, das Backend läuft also bei Bedarf hin und klaut sich den Speicher vom Heap (aber es guckt selber wieviel Speicher es will, das ist einfach mindestens 20, aber meist mehr - z.B. 32 ) - und dann mit [1..20] auffüllen.

    Oder du kannst gar nix machen und einfach mit push_back die Elemente anfügen, da erfährt das Backend immer dass du jetzt Platz für 1, nachher 2, nachher... Elemente brauchst. Wirklich belegen wird das Backend den Platz aber in grösseren Schritten (also sobald du 1 Element reintust z.B. Speicher für 2 Elemente, dann 4, 8, 16, ...).
    Nach einem ersten push_back() ist also size() == 1; capacity(), d.h. der wirklich reservierte Speicher, aber meist >> 1.

    Egal ob ich mit resize oder push_back arbeite, die Kapazität wird doch eh automatisch angepasst.
    Ja. Aber bei resize() kannst du dich irren, und dann hast du potentiell ein Element zuviel oder zuwenig wo nix drin steht oder blöd....

    Das automatische Anpassen der Kapazität bei Push_back hat auch seinen Nachteil: Sobald die aktuelle capacity() überschritten wird, wird (vermutlich, das ist natürlich Implementierungsabhängig) ein neuer kontinuierlicher grösserer Speicherblock belegt, all das Zeugs aus dem alten rüberkopiert (vorausgesetzt der neue ist nicht angrenzend), etc... - das kostet viel Zeit.

    Die Zeit kannst du sparen indem du erst ein reserve() machst - da klaubt er sich im Backend einen grossen Block Speicher - und nachher auffüllst. Seis mit resize() und [] oder (besser) mit push_back.

    Hmm, ich fands irgendwie sinnvoller erstmal den Vektor zu erschaffen (wie ich ihn brauche) und dann mit Werten zu besetzen, als immer ein neues Element hinten dran zu pappen.
    Ja, da hast du recht; genau dafür ist dann reserve() da. Das hätte ich zugegebenermassen auch machen sollen.

    Alles unklar?

    MfG Peschmä
    Geändert von peschmae (24-06-2008 um 20:30 Uhr)
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  5. #5
    Registrierter Benutzer
    Registriert seit
    31.01.2007
    Beiträge
    18
    Ja, da hast du recht; genau dafür ist dann reserve() da. Das hätte ich zugegebenermassen auch machen sollen.
    Also dein Tipp ist also: erstmal reserve, und dann mit push_back, die einzelnen Elemente erstellen?

    Ist vermutlich etwas sicherer als mit resize und vec[i] = x.

    Aha, wieder was gelernt
    Vielen Dank,
    HarryKane

  6. #6
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Genau, wenn man sich denn kurz fassen will.

    MfG Peschmä
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •