3.1 new und delete#

In diesem ersten Aufgabenteil sollen sie einmal den Aufruf von new und delete praktisch umsetzen. Ziel ist es dabei auch den Unterschied von Stack und Heap Speicher noch einmal zu verdeutlichen.

Direkter Link zum Git und JupyterHub.

Aufgabe A: Wiederholung struct#

ToDo:

Als erstes sollen sie hierfür wieder eine struct umsetzen (siehe Aufgabe 2.2 und als Hilfe: Structs ).

In diesem Beispiel wird ein Struct Point erstellt, das lediglich zwei Felder enthält: Die x- und y-Komponenten eines Punktes in 2D.

#include <iostream>
#include <ctime>

// TODO: Definition der Struct für point
// Recap: Implementieren sie eine einfache struct
// Diese soll einen Point wiedergeben, bestehend aus x, y
#include <iostream>
#include <ctime>

// Recap: Implementieren sie eine einfache struct
// Diese soll einen Point wiedergeben, bestehend aus x, y
struct Point { 
    float x, y;
}; 

Aufgabe B: Anlegen von Speicher für die Struct#

Im zweiten Teil soll nun jeweils einmal auf dem Stack und einmal auf dem Heap Speicher für eine solche struct angelegt werden. Dabei wollen wir die verschiedenen Zeiten für die Speicherverwaltung (statisch auf dem Stack im Vergleich zu dynamisch auf dem Heap) messen. Hierfür wiederholen wir jeweils die Erzeugung (und Entfernung) von entsprechenden Variablen.

ToDo: Erzeugen sie jeweils ein Element des structs. Zum einen statisch auf dem Stack (wie bisher auch einfach durch Angabe des Typs) -- zum anderen explizit durch Verwendung von `new`.
int main() {
    // Fuer den Vergleich: wir erzeugen den Point NUM-mal hintereinander.
    int NUM = 10000000;
    std::clock_t start = std::clock();
    for (int i = 0;i<NUM;++i){
        // TODO: Einfaches erzeugen einer Variablen des Typ points.
    }
    std::clock_t dt = std::clock() - start;    
    std::cout << "Stack Time " << float(dt)/CLOCKS_PER_SEC << " sec\n";

    start = std::clock(); 
    // TODO: Analog zu oben sollen sie eine Schleife aufsetzen und darin
    // explizit fuer einen Point Speicher reservieren (und dann wieder freigeben).
    dt = std::clock() - start;
    std::cout << "Heap Time " << float(dt)/CLOCKS_PER_SEC << " sec\n"; 
}
int main() {
    int NUM = 10000000;
    std::clock_t start = std::clock();
    for (int i = 0;i<NUM;++i){
        Point p;
    }
    std::clock_t dt = std::clock() - start;    
    std::cout << "Stack Time " << float(dt)/CLOCKS_PER_SEC << " sec\n";

    start = std::clock(); 
    for(int i = 0; i<NUM; ++i) {
        Point *p = new Point;
        delete p;
    };
    dt = std::clock() - start;
    std::cout << "Heap Time " << float(dt)/CLOCKS_PER_SEC << " sec\n"; 
}
main();

Beobachtungen#

Welche Zugriffszeiten haben sie beobachtet für die beiden verschiedenen Varianten?

Fragen zur Vertiefung und Diskussion (im Plenum):

  • Was haben sie beobachtet?

  • Wie erklären sie sich die unterschiedlichen Laufzeiten?

  • Lesen sie noch einmal die Unterschiede zwischen Stack und Heap nach – warum können wir nicht immer den Stack benutzen und wollen manchmal dynamische Speicherverwaltung einsetzen?

  • Wofür steht das “dynamisch” hier?

Aufgabe C (optional)#

ToDo:

Erzeugen sie nun jeweils einen Array (variieren sie dessen Größe dabei auch in verschiedenen Durchläufen).

  • Wie verändern sich die Laufzeiten und ihre Beobachtungen?

  • Was müssen sie zusätzlich bei der expliziten Erzeugung anpassen (sie sollten den Speicher unbedingt auch wieder freigegeben haben)?

Falls sie noch weiter Zeit haben, können sie hier auch das bisherige struct aus der zweiten Vorlesung einmal einsetzen und dies wiederholen:

int main() {
    int NUM = 10000000;
    std::clock_t start = std::clock();
    for (int i = 0;i<NUM;++i){
        Point p[1000];
    }
    std::clock_t dt = std::clock() - start;    
    std::cout << "Stack Time " << float(dt)/CLOCKS_PER_SEC << " sec\n";

    start = std::clock(); 
    for(int i = 0; i<NUM; ++i) {
        Point *p = new Point[1000];
        delete[] p;
    };
    dt = std::clock() - start;
    std::cout << "Heap Time " << float(dt)/CLOCKS_PER_SEC << " sec\n"; 
}
#include <iostream>
#include <string>
#include <chrono>

// Define a struct to represent a date
struct Date
{
    int day;
    int month;
    int year;
};

// Define a struct to represent a student
struct Student
{
    std::string name;
    Date birthday; // Changed age field to birthday field of type Date
    int studentID;
};