Am Donnerstag, 17. November 2005 19:25 schrieb Johanns Schneider:
also ich hab das gefühl es jetzt verstanden zu haben, das einzige was mich noch wundert ist, dass ich bei dieser main:
int main() { test *Test = new test("test, jo"); //*Test = 0; // Das nullt den Speicher des Objektes delete Test; cout << "noch ist es nicht zu ende\n"; Test->say(); return 0; }
keine fehlermeldung bekomme,
die ausgabe sieht folgendermaßen aus:
test erstellt 0x804b028 test getoetet noch ist es nicht zu ende [leerzeile]
Das liegt daran: new test reserviert Speicher auf dem Heap und gibt die Anfangsadresse an Test zurück. Test enthält also nur die Adresse auf den Speicherbereich (wie jeder Zeiger halt) delete Test. setzt den Speicher lediglich auf "nicht mehr reserviert" es nullt weder den Speicher (ist ja auch unsinnig) noch verändert es den wert der in Test gespeichert ist. (Der zeigt also immer noch auf die Adresse). Und da noch niemand anderes den Speicher reserviert hat steht eben noch genau das selbe in dem Speicherbereich auf den Test zeigt, darum funktioniert test->say() auch noch. Kannst z.B. mal nach dem delete ein variables array einfügen (z.B. mit rand(), feste werte, auch variablen die nicht geändert werden, optimiert der compiler womöglicherweise weg) und danach mal dein Test->say() ausführen. Jetzt wirst du wohl nen speicherzugriffsfehler bekommen, da sich der inhalt des Speichers ja geändert hat.
bei dieser main
int main() { test *Test = new test("test, jo"); //*Test = 0; // Das nullt den Speicher des Objektes delete Test; cout << "noch ist es nicht zu ende\n"; Test->say(); return 0; }
lautet die ausgabe
test erstellt noch ist es nicht zu ende test, jo 0x804b028 test getoetet
Wo ist der unterschied zur ersten main?
sobald ich aber *Test=0; bzw, *Test = NULL; nicht mehr auskommentiere kann ich das programm nicht mehr kompilieren. (siehe alten mails)
*Test = 0; wird fehlschlagen da es für die Klasse Test keinen zuweisungsoperator gibt der einen int in ein Test castet (er will ja hier versuchen Test den wert 0 zuzuweisen) und weder *Test = 0; noch Test = 0; nullen den Speicher aus. um den Speicher wirklich auszunullen müsstest du schreiben memset (Test, 0, sizeof(test)); das ist aber eigentlich unnötig den ein Test = NULL; setzt die Adresse die in Test gespeichert ist auf 0, daher interessiert es Test dann auch nicht mehr ob der ursprüngliche Zeigerbereich ausgenullt ist oder ob da einsen drinne stehen oder n gif Bild. Dieses Test = NULL; hat nur den sinn solch dingen wie in der oberen main zu verhindern. Denn das kann zu sehr schwer zu findenden Fehlern führen. Gruß Andre