wozu Destruktor explizit schreiben?



  • kollja21 schrieb:

    Stände da "erstelle ein Array" oder "Matrix" hätte ich es gleich verstanden. Aber Feld oder noch besser Spielfeld..? interprätiert mal was die damit meinen.

    Für ein Studium ist es Voraussetzung, dass man seinen Verstand benutzt.



  • Du erwartest von einem durchschnittlichem Studenten beinahe unmögliches.



  • @Swordfish
    Danke für die Hilfe



  • kollja21 schrieb:

    Swordfish schrieb:

    kollja21 schrieb:

    Achso, also eine Matrix, bzw. ein 2D-Array?

    Vermutlich. Aber DU sitzt doch in der Vorlesung?

    Wie man das umsetzen soll, weiß ich ja. Ich habe die Formulierung nicht verstanden. Das ist eben das Blöde, wenn es für ein Wort 10 Synonyme gibt. Stände da "erstelle ein Array" oder "Matrix" hätte ich es gleich verstanden. Aber Feld oder noch besser Spielfeld..? interprätiert mal was die damit meinen.

    Spielfeld ist die fachliche Anforderung. Darauf, dass ein Spielfeld technisch mit einem Array oder einer Matrix implementiert wird, sollte der Entwickler kommen. Das ist in der Regel so, dass die Anforderungen fachlich gestellt sind und damit natürlich fachliche Begriffe verwendet werden.

    Bist Du in der Schule oder in der Uni? In der Schule wird nach der Lösung einer Aufgabe mit Hilfe eines bestimmten Werkzeugs gefragt. In der Uni sollte hoffentlich das Werkzeug nicht angegeben werden sondern nur die Aufgabe. So ist das zumindest spätestens in der beruflichen Praxis.

    Ein Ingenieur bekommt ja keine Aufgabe: wähle eine geeignete Schraube indem Du die Belastung berechnest, sondern es ergibt sich die Aufgabe, 2 Teile miteinander zu verbinden. Er muss erkennen, dass eine Schraube das geeignete Mittel darstellt und muss wissen, dass er diese Schraube als nächstes dimensionieren muss.



  • tntnet schrieb:

    (...)Bist Du in der Schule oder in der Uni? In der Schule wird nach der Lösung einer Aufgabe mit Hilfe eines bestimmten Werkzeugs gefragt. In der Uni sollte hoffentlich das Werkzeug nicht angegeben werden sondern nur die Aufgabe. So ist das zumindest spätestens in der beruflichen Praxis.

    Ein Ingenieur bekommt ja keine Aufgabe: wähle eine geeignete Schraube indem Du die Belastung berechnest, sondern es ergibt sich die Aufgabe, 2 Teile miteinander zu verbinden. Er muss erkennen, dass eine Schraube das geeignete Mittel darstellt und muss wissen, dass er diese Schraube als nächstes dimensionieren muss.

    Um auf dein Beispiel einzugehen, meine Aufgabe lautet nicht "hier sind 2 Teile. Verbinde sie." sondern "hier sind 2 Teile, verbinde sie unter folgenden Bedingungen: ... ." Nun kann es einem Menschen passieren, ob er aus der Schule, Uni oder der Berufswelt kommt, dass er die sprachliche Formulierung nicht eindeutig versteht. Und weil ich kein C++ Guru bin, und mir nicht sicher bin was ich jetzt nicht verstanden habe, frage ich.



  • Es ergibt für mich leider immer noch keinen Sinn.
    Wenn ich im Konstruktor, der ja auch nur eine Funktion ist, eine Variable/Pointer, was auch immer, anlege, dann wird es doch nach dem Beenden der Funktion/Konstruktor, von selbst wieder gelöscht. Oder nicht?
    Also müsste ich bereits vor dem Kontruktor - im private-Bereich der Klasse - die Matrix anlegen. Dann macht aber die Allokation im Konstruktor wieder keinen Sinn.



  • Ja, aber wenn du im Konstruktor new schreibst, musst du im Destruktor delete schreiben.



  • @Nathan: Er redet von lokalen Variablen im ctor ... hat Membervariabled noch ned durchschaut. Aber dazu mag ich jetzt vom phone nix tippen ...



  • Swordfish schrieb:

    @Nathan: Er redet von lokalen Variablen im ctor ... hat Membervariabled noch ned durchschaut. Aber dazu mag ich jetzt vom phone nix tippen ...

    Ok. In dem Fall:
    Ja, dann musst du die Variable im privaten Bereich anlegen. Aber du weißt du nicht wie groß der Speicher sein wird, sagst du? Ja, das weißt du nicht. Also kannst du lediglich einen Pointer anlegen*. Im Konstruktor weißt du wie groß der Speicher sein wird, also forderst du Speicher der entsprechenden Größe an. In diesem Fall musst du den dann auch im Destruktor löschen.

    *Bessere Variante wäre ein passender Container, der kümmert sich um Allokation und Deallokation automatisch.



  • Nathan schrieb:

    Ja, aber wenn du im Konstruktor new schreibst, musst du im Destruktor delete schreiben.

    Meine Frage ist, wozu man überhaupt im Konstruktor(einer Funktion) mit new oder ohne etwas erzeugen sollte, wenn man es außerhalb des Konstruktors nutzen möchte, wenn man doch keinen Zugriff darauf hat? Oder irre ich mich?



  • kollja21 schrieb:

    Nathan schrieb:

    Ja, aber wenn du im Konstruktor new schreibst, musst du im Destruktor delete schreiben.

    Meine Frage ist, wozu man überhaupt im Konstruktor(einer Funktion) mit new oder ohne etwas erzeugen sollte, wenn man es außerhalb des Konstruktors nutzen möchte, wenn man doch keinen Zugriff darauf hat? Oder irre ich mich?

    Siehe meinen neuesten Post.



  • @kollja21:
    Du hast wirklich keinen Schimmer, aber davon ganz schön viel! Wie hast du bloß die Schule geschafft?



  • Nathan schrieb:

    dann musst du die Variable im privaten Bereich anlegen. Aber du weißt du nicht wie groß der Speicher sein wird, sagst du? Ja, das weißt du nicht. Also kannst du lediglich einen Pointer anlegen*. Im Konstruktor weißt du wie groß der Speicher sein wird, also forderst du Speicher der entsprechenden Größe an. In diesem Fall musst du den dann auch im Destruktor löschen.

    ok, das macht Sinn. Meine Variable ist eine Matrix. Kannst du mir kurz hinschreiben, wie ein Pointer auf eine 2D-Matrix unbestimmter Größe aussieht? bitte 🙂



  • kollja21 schrieb:

    ...Kannst du mir kurz hinschreiben, wie ein Pointer auf eine 2D-Matrix unbestimmter Größe aussieht? bitte 🙂

    Wieso unbestimmter Größe?
    ...(int rows, int cols) => Größe ist vorgegeben.

    Beispielsweise:
    int * matrix = new int[rows*cols];



  • Das Lustige ist, es steht schon in der Aufgabenstellung:

    kollja21 schrieb:

    class Bla {
    public:
        Bla(int rows, int cols);
        ~Bla();
    // weitere Methoden
    };
    

    "Implementieren Sie den Konstruktor Bla(int rows, int cols). Dieser soll den für ein Spielfeld mit rows Reihen und cols Spalten benötigten Speicher automatisch allozieren. Legen Sie die für den Zugriff auf das Spielfeld nötigen Variablen im private Bereich der Klasse an. Implementieren Sie außerdem den Destruktor ~Bla(), der den für das Spielfeld allozierten Speicher wieder frei gibt."

    ➡

    class Bla {
    private:
        irgendein_typ * field;
    public:
        Bla(int rows, int cols)
        {
            // mach was mit field ... *)
        }
        ~Bla();
    // weitere Methoden
    };
    

    😉 besser: mach was mit field in der Initialisierungsliste ... aber das machen wir dann morgen.



  • asc schrieb:

    Wieso unbestimmter Größe?
    ...(int rows, int cols) => Größe ist vorgegeben.

    Beispielsweise:
    int * matrix = new int[rows*cols];

    rows und cols geben zum Zeitpunkt der Deklaration nur die "Größe"/Anzahl der Dimmensionen an. Also zwei. Aber wie groß die Matrix wird, wird erst im Konstruktor bekannt. Deswegen sagte ich unbestimmter Größe.
    das hier: new int[rows*cols] kann ich in der Deklaration nicht verwenden, weil rows und cols selbst noch leer sind. Außerdem würden sie doch multipliziert werden, oder nicht? Dann hätte ich weiterhin ein 1D-Array.



  • kollja21 schrieb:

    asc schrieb:

    Wieso unbestimmter Größe?
    ...(int rows, int cols) => Größe ist vorgegeben.

    Beispielsweise:
    int * matrix = new int[rows*cols];

    das hier: new int[rows*cols] kann ich in der Deklaration nicht verwenden, weil rows und cols selbst noch leer sind.

    Richtig. Deshalb machst du die Zuweisung des Pointers auch erst im Konstruktor.

    Außerdem würden sie doch multipliziert werden, oder nicht? Dann hätte ich weiterhin ein 1D-Array.

    Richtig. Aber ein 1D-Array ist das einzige was du bekommen kannst. Mehrdimensionale dynamische Arrays gibt es in C++ nicht*+. Du kannst aber ein eindimensionales Array wie ein mehrdimensionales Array behandeln, musst nur ein paar Indextricks anwenden:

    array[x][y] -> array[y * x_size + x] oder array[x * y_size + y]
    

    *Es gibt höchstens ein eindimensionales Array von Pointern auf einzelne Arrays. Das ist aber keine richtige Matrix und total umständlich.
    +Genau genommen gibt es auch keine mehrdimensionalen statischen Arrays, der Compiler macht da die selben Tricks wie beschrieben.



  • Nathan schrieb:

    (...) *Es gibt höchstens ein eindimensionales Array von Pointern auf einzelne Arrays. Das ist aber keine richtige Matrix und total umständlich.
    +Genau genommen gibt es auch keine mehrdimensionalen statischen Arrays, der Compiler macht da die selben Tricks wie beschrieben.

    DANKE!!! das ist echt super hilfreich 🙂



  • Ich habe den folgenden Code:

    class Bla {
    private:
    	int* Matrix[];
    public:
    	Bla(int rows, int cols);
    	~Bla();
    };
    Bla::Bla(int r, int c) {
    	*Matrix = new int[r * c];
    }
    Bla::~Bla(void) {
    	delete[] Matrix;
    }
    

    Und diese Meldung bei Zeile 12: "deleting array '((Bla*)this)->Bla::Matrix' [enabled by default]"
    Was bedeutet sie?



  • In Zeile 3 dekarierst du einen Pointer auf ein Array unbestimmter Größe. Das ist quasi ein Pointer auf ein Pointer.
    In Zeile 9 weist du diesem Pointer das Ergebnis von new[] zu.
    In 12 zerstörst du den Pointer.
    Schneller Fix:

    delete[] *Matrix;
    

    Besserer Fix:

    class Bla {
    private:
        int* Matrix; // ein Pointer reicht
    public:
        Bla(int rows, int cols);
        ~Bla();
    };
    Bla::Bla(int r, int c) {
        Matrix = new int[r * c]; // keine Dereferenzierung
    }
    Bla::~Bla(void) {
        delete[] Matrix;
    }
    

Anmelden zum Antworten