JGU Logo JGU Logo JGU Logo JGU Logo

Institut für Informatik

Michael Wand
Christian Ali Mehmeti-Göpel
Wintersemester 2020/21DIGITAL

Blatt 05

Aufgabe 03
Einführung in die Softwareentwicklung



Aufgabe Vector

Letzte Änderung: 14. December 2020, 11:03 Uhr
25 Punkteim Detail
Ansicht:   |  

Mit std::vector haben Sie bereits auf vergangenen Blättern gearbeitet. std::vector ist ein sehr effektiver Weg, um manuelle Speicherverwaltung mittels new[] and delete[] zu umgehen. Generell sollten Sie in allen folgenden Aufgabenblättern std::vector verwenden, anstatt Speicher für Arrays selbst zu verwalten. Eine vollständige Liste der unterstützten Operationen von std::vector erhalten Sie auf https://en.cppreference.com/w/cpp/container/vector .


In dieser Aufgabe wollen wir std::vector teilweise nachimplementieren, um die internen Mechanismen zu verstehen. Es geht hier also explizit darum, den Speicher manuell zu verwalten. Denken Sie bei manueller Speicherverwaltung immer an die rule of three!


Ein std::vector<T> speichert intern einen Pointer auf ein C-Array vom Typ T. Der std::vector ist dabei der "Owner" des C-Arrays, das heißt, dass der std::vector das Array selbst anlegt und am Ende seiner Lebenszeit das C-Array eigenständig löscht. Sie können C-Arrays eines Typs T mittels new T[n] dynamisch allokieren, dabei ist n die Größe des Arrays. Arrays lassen sich nicht nachträglich vergrößern oder verkleinern. Falls also eine Operation ein größeres C-Array benötigen würde (z.B. push_back), erzeugen wir ein neues C-Array mit doppelter Länge (oder Länge 8, falls das Array zu Beginn leer war) und kopieren alle Werte vom alten C-Array in das neue C-Array um. Intern müssen wir uns also nicht nur merken, wie groß das C-Array ist ("Kapazität"), sondern auch, wie viele Elemente wir darin gespeichert haben ("Größe"). Achten Sie darauf, das alte C-Array zu löschen, falls Sie es gegen ein neues ersetzen.


Weil wir mit Templates arbeiten, muss vector vollständig im Header implementiert werden.


Implementieren Sie folgende Funktionen:



Natürlich dürfen Sie auch Hilfsfunktionen nach eigenem Ermessen hinzufügen, um die Implementierung übersichtlicher zu halten.


Sie können diesen Codeschnipsel zum Testen verwenden.
#include <iostream>

int main(){
    vector<int32_t> myvec;

    for(int32_t i = 0; i < 200; i++)
        myvec.push_back(i);

    // 200
    std::cout << myvec.size() << std::endl;
    // 256
    std::cout << myvec.capacity() << std::endl;

    myvec.shrink_to_fit();

    // 200
    std::cout << myvec.size() << std::endl;
    // 200
    std::cout << myvec.capacity() << std::endl;

    for(size_t i = 0; i < myvec.size(); ++i)
        std::cout << myvec[i] << "   ";
    std::cout << std::endl;
}