2017-07-25 6 views
0

Also im Grunde versuche ich diesen Code aus, kompiliert in cl (Visual Studio C++ Compiler) und es druckt weiter 0. Sollte nicht gleich nullptr sein? KeineZwei Zeiger nicht richtig gelöscht

#include <iostream> 
#include <string> 
using namespace std; 
int main() { 
    int* x; 
    x = new int(5); 
    int* y; 
     y = x; 
    delete x; 
    x = nullptr; 
    cout <<(y==nullptr)<< endl; 
    return 0; 
} 
+3

Sie haben zwei verschiedene Variablen, die jeweils eine * Kopie * voneinander enthalten (anfänglich). Es ist so, als hätte man z.B. 'int x = 5; int y = x; x = 0; 'und dann wundern, warum' y' auch nicht gleich '0' ist? –

+3

Ich verstehe den Downvoting nicht. Dies ist gut geschrieben mit einem kompilierbaren Beispiel. Bitte nicht aus Gründen der Offensichtlichkeit ablehnen. – Bathsheba

+0

Wie überprüfe ich, ob y auf beschädigten Speicher verweist, bevor er gelöscht wird? – JukesOnYou

Antwort

5

, das Setzen von x-nullptr nicht y-nullptr auch nicht gesetzt.

y ist eine int* keine Referenz auf ein int*.

So y == nullptr ist unbedingt false.


Für das Pub Quiz: xnichtnullptr sein, da, wenn eine Zuweisung dann versagt std::bad_alloc geworfen worden wäre. Es würde möglich sein y sein nullptr Sie x = new(std::nothrow) int(5);

+2

* "Kneipenquiz" * - Nicht sicher, ob Tippfehler oder ausgezeichnetes Wortspiel. – StoryTeller

0

Zeiger sind noch normale Variablen geschrieben hatte, mit einem rechten und einem linken Wert.

Sie sind speziell nur in der Tatsache, dass ihr richtiger Wert eine Adresse eines Speicherplatzes ist, der vom Benutzer verwaltet werden kann.

In Ihrem Fall sind sowohl x als auch y irgendwo auf dem Stapel zugeordnet. Wo Sie y=x tun setzen Sie den Wert von y den gleichen Wert von x zu sein, aber später, wenn Sie x=nullptr ändern Sie nur den Wert von x, nicht den Wert von y.

Auch achten Sie auf die Tatsache, dass während vor delete x sowohl x und y auf eine gültige Adresse beziehen, nachdem es x richtig auf eine nullptr gesetzt, während y die Adresse nun ungültigen Speicher behält. Dies ist ein Fall von pointer aliasing, der mehrere Probleme verursachen kann, vor allem ungültige Speicherzugriffsfehler.

0

Nr

die Zeile für Zeile gehen lassen:

x = new int(5); //allocate an integer, set it to 5 and return a pointer to it (x will not nullptr). 
int* y; //allocate local storage to another pointer. 
y = x; //copy the (not nullptr) value of x into y. 
delete x; //de-allocate the space previously allocated. 
//At this point the value of x is unchanged and y is equal to it. 
//De-referencing x (*x) however is undefined because it was deallocated. 
x = nullptr; //Set x to nullptr. Has no effect on y. 
cout <<(y==nullptr)<< endl; //y still equals the (now invalid) value allocated above. 

eine Variable auf eine andere Variable Zuordnung ist eine einmalige Sache. Danach werden die Änderungen in der einen sich nicht in der anderen widerspiegeln (obwohl die Änderungen "durch" die andere beeinflussen können).

0

Was tatsächlich geschieht hier:

  1. Sie deklarieren einen neuen Zeiger vom Typ int als x.
  2. Sie zeigen X auf einen neuen int.
  3. Sie deklarieren einen neuen Zeiger als y.
  4. Sie ordnen den Wert von x dem Wert von y zu, dh y zeigt jetzt auch auf den neuen int.
  5. Sie löschen x.
  6. Sie drucken das Ergebnis einer bedingten Operation, die prüft, ob y gleich nullptr ist, was falsch ist, da y immer noch auf int zeigt und einen Wert hat. Somit wird das Ergebnis als 0 ausgegeben, d. H. Als falsch.
  7. Sie geben 0 zurück! : P
2

Ein Zeiger ist nicht "gelöscht". Die Löschoperation hebt den Speicherblock auf, auf den der Zeiger zeigt, und lässt diesen Zeiger unverändert. Es ist nicht auf nullptr eingestellt und zeigt nicht auf "nichts" (übrigens löschen Sie es explizit).

Und ein Zeiger verhält sich wie eine gewöhnliche Variable und hält einen Wert (eine Adresse). Das Ändern des Wertes einer Variablen beeinflusst keinen anderen (außer im Fall von Aliasing, aber das ist eine andere Geschichte.)

+1

* "und lässt diesen Zeiger unverändert." * - Das ist Interpretation. Nach der Operation ist der Zeigerwert offiziell ungültig. Und das eröffnet eine ganze Reihe von implementierten definierten Spielereien, mit denen der Standard vollkommen in Ordnung ist. – StoryTeller

+0

@StoryTeller: Ich kann dir überhaupt nicht folgen. Wenn vor dem Löschen der Zeiger 0x43FF4500 enthält, hält er nach dem Löschen immer noch 0x43FF4500, ganzer Stopp. Sie machen den gleichen Fehler wie das OP und glauben, dass es eine Voodoo-Beziehung zwischen der Zeigervariablen und dem Speicherblock gibt, auf den sie einmal gezeigt hat. Zum Beispiel wäre es harmlos, den "offiziell ungültigen" Zeigerwert auf einen anderen Zeiger zu kopieren. –

+1

Das ist reich. Ich schlage vor, dass Sie tatsächlich über adprees Invalidation lesen, was es bedeutet, wie Implementierung definiertes Verhalten betroffen ist, und wie Ihre Annahme, dass 'x == y 'unmittelbar nach dem Löschen Ausdruck ist nicht durch den Standard vorgeschrieben. – StoryTeller