Überschreibung meines Pointers



  • @Darktutnix sagte in Überschreibung meines Pointers:

    <iostream> ist schon Eingebunden und durch #program once in iostream passiert genau garnichts. (auser das ist dort nicht vorhanden was ich mir nicht vorstellen kann)

    Ja. Bei dir. Jetzt. Aber Headerdateien werden oft auch von anderem Code verwendet dessen Programmierer nicht damit rechnet, daß du darin solche #defines hast. Auch ist das Einbinden von <iostream> in deiner binärer_suchbaum.h ziemlich sinnfrei, weil der Header <iostream> garnicht braucht.

    @Darktutnix sagte in Überschreibung meines Pointers:

    hmm ... ist für mich nicht nachvollziehbar, warum die nur eine Lebensperiode haben sollen. Ist es wirklich das was ich meinte mit dem Pointer der Funktion anstelle des rückgabe Objekts?

    Das Objekt, das zurückgegeben wird ist ein Temporary davon nimmst du die Adresse. Sobald dieses Temporary das Zeitliche segnet ist diese Adresse ein invalid-pointer-value und du kannst dir von mir aus ausdrucken und and die Wand hängen aber sonst nichts sinnvolles mehr damit anstellen - vor allem nicht dereferenzieren.

    Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created.

    Was auch seltsam ist: Warum sind die Funktionen die mit deinem Baum arbeiten freie Funktionen denen ein Baum übergeben wird (wie man es in C machen würde) und keine Member?


  • Mod

    template <typename T>
    BaumKnoten<T> create(T var);
    

    Dieses Funktionstemplate wird in einem Aufruf immer einen prvalue Ausdruck ergeben, d.h. einen Ausdruck der für sich genommen gar kein Objekt benennt, sondern erst einmal nur einen Wert darstellt.
    Wenn wir auf diesen Ausdruck nun den Adress-Operator anwenden, wird die Erzeugung eines tatsächlichen Objekts veranlasst, welches mit diesem Wert initialisiert wird und dessen Adresse ergeben wird. Aber dieses Objekt existiert nur über eine begrenzte Zeitspanne, i.A. bis zum Ende des Statements in dem es erzeugt worden ist. In der Tat ist es ziemlich unsinnig, dass eine Funktion die rohe Adresse eines neuen Objektes zurückgibt, da der Speicher dafür irgendwo auf dem Heap alloziert worden sein muss.

    Du könntest statt einem Zeiger start einfach einen leeren suchbaum::BaumKnoten<standart_type> start = {} definieren, der ausgenullt ist, und dann an einfuegen die Adresse von start übergeben. (Um Nullzeiger als Argumente brauchst du dich dann nicht mehr zu sorgen, das wäre nicht länger intendiert).



  • @Swordfish sagte in Überschreibung meines Pointers:

    @Darktutnix sagte in Überschreibung meines Pointers:

    <iostream> ist schon Eingebunden und durch #program once in iostream passiert genau garnichts. (auser das ist dort nicht vorhanden was ich mir nicht vorstellen kann)

    Ja. Bei dir. Jetzt. Aber Headerdateien werden oft auch von anderem Code verwendet dessen Programmierer nicht damit rechnet, daß du darin solche #defines hast. Auch ist das einbinden von <iostream> in deiner binärer_suchbaum.h ziemlich sinnfrei, weil der Header <iostream> garnicht braucht.

    Hmm ... ganz erlich xD ich habe noch nie mit anderen Coder gearbeitet und denke auch bei diesen "Programmen" nicht darüber nach ob die jemals nochjemand sieht. Aber es ist aufjedenfall Wichtig sowas später zu beachten.

    Was auch seltsam ist: Warum sind die Funktionen die mit deinem Baum arbeiten freie Funktionen denen ein Baum übergeben wird (wie man es in C machen würde) und keine Member?

    Weil das die Aufgabenstellung ist. Wir haben extrem enge Rahmenbedingugnen im ersten Semester (ich selbst Programmiere schon länger, das meiste selbst beigebracht, weswegen ich mir selbst die Template Aufgabe gestellt habe), aber eigentlich ist es nicht möglich (bzw nicht erlaubt was keine Klausurzulassung bedeutet), wobei die Dozenten bei der Abgabe bei solchen kleinen änderungen nix sagen (Grundlegend ändere ich ja nichts an der Funktionsweise durch das Template). Würde ich jetzt allerdings auf Klassen vorgreifen, dürfte ich das ganze nochmal machen. Auserdem sind Globale/static vars explizit untersagt.

    Andere möglichkeit würde mir jetzt nicht einfallen. Oder was meinst du mit "Member"? Klassen oder?

    @Columbo sagte in Überschreibung meines Pointers:

    template <typename T>
    BaumKnoten<T> create(T var);
    

    Dieses Funktionstemplate wird in einem Aufruf immer einen prvalue Ausdruck ergeben, d.h. einen Ausdruck der für sich genommen gar kein Objekt benennt, sondern erst einmal nur einen Wert darstellt.
    Wenn wir auf diesen Ausdruck nun den Adress-Operator anwenden, wird die Erzeugung eines tatsächlichen Objekts veranlasst, welches mit diesem Wert initialisiert wird und dessen Adresse ergeben wird. Aber dieses Objekt existiert nur über eine begrenzte Zeitspanne, i.A. bis zum Ende des Statements in dem es erzeugt worden ist. In der Tat ist es ziemlich unsinnig, dass eine Funktion die rohe Adresse eines neuen Objektes zurückgibt, da der Speicher dafür irgendwo auf dem Heap alloziert worden sein muss.

    Du könntest statt einem Zeiger start einfach einen leeren suchbaum::BaumKnoten<standart_type> start = {} definieren, der ausgenullt ist, und dann an einfuegen die Adresse von start übergeben. (Um Nullzeiger als Argumente brauchst du dich dann nicht mehr zu sorgen, das wäre nicht länger intendiert).

    Also Grundlegend muss ich eine template<type> immer inizalisieren (also zb suchbaum::BaumKnoten<standart_type> start = {} so) damit es nicht temporär erzeugt wird? Wenn ich einfach nur sage ich habe ein template<type> und fülle da s jetzt wie ich es in create mache erzeuge ich nur temporäre daten?

    Aber pointer auf so suchbaum::BaumKnoten<standart_type> start = {} initalisierte sachen verschieben sich nicht nach lust und laune? (also ich mache start und gebe jetzt *start weiter)

    Danke für die Hilfe 😃



  • @Darktutnix sagte in Überschreibung meines Pointers:

    Andere möglichkeit würde mir jetzt nicht einfallen. Oder was meinst du mit "Member"? Klassen oder?

    struct und class ist dasselbe. Bei einer struct sind die Member standardtmäßig public, bei einer class sind die Member standardtmäßig private. Sonst gibt es keinen Unterschied.

    struct foo { // alles folgende ist public ...
        int qux;  // Member
        foo() : qux{ 42 } {}  // Konstruktor
        int bar() { return return qux; }  // Memberfunktion *)
    private: // ... jetzt nimmer
        int haensel;
    };
    

    1:1 dasselbe:

    class foo { // alles folgende ist private ...
        int haensel;
    public: // ... jetzt nimmer
        int qux;  // Member
        foo() : qux{ 42 } {}  // Konstruktor
        int bar() { return return qux; }  // Memberfunktion *)
    };
    

    * ) Für die Klugscheißer, ja, es ist eine Funktion weil es "Memberfunktionen" im C++ Sprachgebrauch eigentlich nicht gibt.

    @Darktutnix sagte in Überschreibung meines Pointers:

    Also Grundlegend muss ich [...]

    Ich glaube du hast da einen Knoten im Hirn.

    foo_type bar() { foo_type foo; return foo; }
    

    gibt ein temporäres Objekt vom Typ foo_type zurück. In

    bar();
    

    lebt dieses Temporary genau bis zum Semikolon. Keinen Wimpernschlag länger. Wenn du jetzt von diesem temporären Objekt

    foo_type *p = &bar(); // die Aresse nimmst
    

    ist das gut und schön, aber es bringt dir nix, weil der Zeiger schon in der nächsten Zeile in die Pampa zeigt weil das zurückgegebene Objekt dann nicht mehr existiert. Deshalb sollst du ein

    foo_type foo;  // nehmen (ob das ein template ist oder nicht ist egal)
    foo = bar();  // und das zurückgegebene Temporary darin speichern
    

    damit du noch lange Freude daran hast 🙂



  • Anscheinend hab ich es immer noch nicht richtig verstanden...

    if (temp->GetVar() > var) {
    			if (temp->GetLower() == nullptr) {
    				BaumKnoten<T> c = {};
    				c.SetVar(var);
    				temp->SetLower(&c);
    				return save;
    			}
    			else
    				temp = temp->GetLower();
    

    ich erzeuge erstmal nen leeren BaumKnoten dann überschreibe ich diesen mit dem was ich bei var bekomme und nehme mir dann den pointer und speicher den in meinem Baum ab ... trozdem ist es nur eine Temporär erstellte datei ... dat will nicht in meinen Schädel x.x

    (merke ich daran das er von selbst verschwiendet wie start vorher) und ich bekomme nichts ... weder warnungen noch fehlermeldungen x.x



  • Wann wird c zerstört? Ist die Adresse dann noch gültig?



  • @manni66 sagte in Überschreibung meines Pointers:

    Wann wird c zerstört? Ist die Adresse dann noch gültig?

    Er findet eine addresse irgendwo in der Pampa. Wie bei Start sobald ich die erste ausgabe mache. (vermutlich etwas früher der Debugger ist ja etwas Zeit verzögert)

    Dann wird aus dem ersten Zeiger in start ein extrem seltsamer, der sich ständig verändert.



  • Du sollst über die Frage nachdenken. Wann c zerstört wird ist klar definiert!



  • @manni66 sagte in Überschreibung meines Pointers:

    Du sollst über die Frage nachdenken. Wann c zerstört wird ist klar definiert!

    x.x ich glaub ich bin durch für heute ...

    Klar auf die Variabele C kann ich irgendwann nicht mehr zugreifen, aber deswegen muss sie doch noch da sein. Ich Zerstöre nirgendwo c expliziet. Und Garbish Collector existiert doch nicht ...



  • @Darktutnix sagte in Überschreibung meines Pointers:

    Klar auf die Variabele C kann ich irgendwann nicht mehr zugreifen, aber deswegen muss sie doch noch da sein. Ich Zerstöre nirgendwo c expliziet. Und Garbish Collector existiert doch nicht ...

    Das geht automatisch. Das ist doch gerade der Witz an C++:

    automatic storage duration. The storage for the object is allocated at the beginning of the enclosing code block and deallocated at the end. All local objects have this storage duration, except those declared static, extern or thread_local.


Anmelden zum Antworten