Ü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
#define
s hast. Auch ist das Einbinden von<iostream>
in deinerbinä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?
-
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 leerensuchbaum::BaumKnoten<standart_type> start = {}
definieren, der ausgenullt ist, und dann aneinfuegen
die Adresse vonstart
ü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
#define
s hast. Auch ist das einbinden von<iostream>
in deinerbinä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 leerensuchbaum::BaumKnoten<standart_type> start = {}
definieren, der ausgenullt ist, und dann aneinfuegen
die Adresse vonstart
ü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 sageich habe ein template<type> und fülle da s jetzt
wie ich es increate
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
undclass
ist dasselbe. Bei einerstruct
sind die Member standardtmäßigpublic
, bei einerclass
sind die Member standardtmäßigprivate
. 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. Inbar();
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.