Ich habe mich immer gefragt, warum die automatische Einstellung des Zeigers auf NULL nach dem Löschen nicht zum Standard gehört. Wenn dies behoben wird, treten viele der Abstürze aufgrund eines ungültigen Zeigers nicht auf. Ich kann mir jedoch einige Gründe vorstellen, warum der Standard dies eingeschränkt hätte:
Performance:
Eine zusätzliche Anweisung kann die
delete
Leistung beeinträchtigen.Könnte es an
const
Zeigern liegen.Andererseits hätte Standard wohl etwas für diesen speziellen Fall tun können.
Kennt jemand genaue Gründe dafür, dies nicht zuzulassen?
Erstens würde das Setzen auf Null eine im Speicher gespeicherte Variable erfordern. Es ist wahr, dass Sie normalerweise einen Zeiger in einer Variablen haben, aber manchmal möchten Sie vielleicht ein Objekt an einer gerade berechneten Adresse löschen . Das wäre unmöglich mit "annullieren" löschen.
Dann kommt die Leistung. Möglicherweise haben Sie den Code so geschrieben, dass der Zeiger unmittelbar nach dem Löschen den Gültigkeitsbereich verlässt . Es ist nur Zeitverschwendung, es mit Null zu füllen. Und C ++ ist eine Sprache mit der Ideologie "Brauchen Sie es nicht? Dann müssen Sie nicht dafür bezahlen".
Wenn Sie Sicherheit benötigen, stehen Ihnen zahlreiche intelligente Zeiger zur Verfügung, oder Sie können Ihre eigenen schreiben - besser und intelligenter.
quelle
delete (ptr + i)
Sie können mehrere Zeiger haben, die auf diesen Speicher zeigen. Es würde ein falsches Sicherheitsgefühl erzeugen, wenn der Zeiger, den Sie für das Löschen angegeben haben, auf null gesetzt würde, alle anderen Zeiger jedoch nicht. Ein Zeiger ist nichts anderes als eine Adresse, eine Zahl. Es könnte genauso gut ein Int mit einer Dereferenzierungsoperation sein. Mein Punkt ist, dass Sie auch jeden einzelnen Zeiger scannen müssten, um diejenigen zu finden, die auf denselben Speicher verweisen, den Sie gerade gelöscht haben, und sie ebenfalls auf Null setzen. Es wäre rechenintensiv, alle Zeiger nach dieser Adresse zu durchsuchen und sie auf Null zu setzen, da die Sprache nicht dafür ausgelegt ist. (Obwohl einige andere Sprachen ihre Referenzen so strukturieren, dass ein ähnliches Ziel auf andere Weise erreicht wird.)
quelle
Ein Zeiger kann in mehr als einer Variablen gespeichert werden. Wenn Sie einen dieser Zeiger auf NULL setzen, bleiben in den anderen Variablen immer noch ungültige Zeiger übrig. Sie gewinnen also nicht wirklich viel, sondern schaffen eher ein falsches Sicherheitsgefühl.
Außerdem können Sie Ihre eigene Funktion erstellen, die das tut, was Sie wollen:
quelle
Weil es nicht wirklich nötig ist und weil es das Löschen erfordern würde, Zeiger zu Zeiger zu nehmen und nicht nur Zeiger.
quelle
delete
wird hauptsächlich in Destruktoren verwendet. In diesem Fall ist es sinnlos, ein Mitglied auf NULL zu setzen. Einige Zeilen später, zum Abschluss}
, existiert das Mitglied nicht mehr. Bei Zuweisungsoperatoren folgt auf eine Löschung normalerweise ohnehin eine Zuweisung.Außerdem würde der folgende Code illegal sein:
quelle
Hier ist ein weiterer Grund; Angenommen, delete setzt sein Argument auf NULL:
Sollte die Leiste auf NULL gesetzt werden? Können Sie das verallgemeinern?
quelle
Wenn Sie über ein Array von Zeigern verfügen und Ihre zweite Aktion darin besteht, das leere Array zu löschen, ist es sinnlos, jeden Wert auf Null zu setzen, wenn der Speicher freigegeben werden soll. Wenn du willst, dass es null ist, schreibe null darauf :)
quelle
In C ++ können Sie Ihren eigenen Operator neu definieren und löschen, damit er beispielsweise Ihren eigenen Pool-Allokator verwendet. Wenn Sie dies tun, ist es möglich, new zu verwenden und mit Dingen zu löschen, die nicht ausschließlich Adressen sind, sondern Indizes in Ihrem Pool-Array enthalten. In diesem Zusammenhang kann der Wert von NULL (0) eine rechtliche Bedeutung haben (bezogen auf das erste Element im Pool).
Wenn also delete NULL automatisch auf sein Argument gesetzt hat, hat dies nicht immer die Bedeutung von - setze den Wert auf einen ungültigen Wert. Der ungültige Wert ist möglicherweise nicht immer NULL.
quelle
Die Philosophie von C ++ lautet "Bezahlen Sie nur, wenn Sie es verwenden". Ich denke, es könnte Ihre Frage beantworten.
Manchmal könnten Sie auch einen eigenen Heap haben, der gelöschten Speicher wiederherstellt. Oder manchmal einen Zeiger, der keiner Variablen gehört. Oder Zeiger in wenigen Variablen gespeichert - es ist möglich, nur eine davon auf Null zu setzen.
Wie Sie sehen können, gibt es viele Probleme und mögliche Probleme.
quelle
Das automatische Setzen des Zeigers auf NULL würde die meisten Probleme mit einer schlechten Zeigernutzung nicht lösen. Der einzige Absturz, den es vermeiden würde, ist, wenn Sie versuchen, es zweimal zu löschen. Was ist, wenn Sie eine Member-Funktion für einen solchen Zeiger aufrufen? Es würde immer noch abstürzen (vorausgesetzt, es greift auf Mitgliedsvariablen zu). C ++ hindert Sie nicht daran, Funktionen für NULL-Zeiger aufzurufen, und sollte dies auch nicht unter Leistungsgesichtspunkten tun.
quelle
Ich sehe Leute, die seltsame Antworten auf diese Frage geben.
ptr = NULL; Wie kann eine so einfache Aussage zu Leistungsverzögerungen führen?
Eine andere Antwort lautet, dass mehrere Zeiger auf denselben Speicherort zeigen können. Sicher können wir. In diesem Fall würde eine Löschoperation an einem Zeiger nur diesen Zeiger NULL machen (wenn Löschen den Zeiger NULL macht) und der andere Zeiger wäre nicht NULL und würde auf den freien Speicherort zeigen.
Die Lösung hierfür sollte sein, dass der Benutzer alle Zeiger löschen sollte, die auf dieselbe Position zeigen. Intern sollte geprüft werden, ob der Speicher bereits freigegeben ist, als nicht freigegeben. Machen Sie nur den Zeiger NULL.
Stroustrup hätte das Löschen so gestalten können. Er dachte, Programmierer würden sich darum kümmern. Also ignorierte er es.
quelle