Frage

Ich habe also einen Zeiger auf ein Array von Zeigern.Wenn ich es so lösche:

delete [] PointerToPointers;

Werden dadurch auch alle Zeiger gelöscht, auf die verwiesen wird?Wenn nicht, muss ich alle Zeiger durchlaufen und sie ebenfalls löschen, oder gibt es eine einfachere Möglichkeit, dies zu tun?Mein Google-Fu scheint mir keine guten Antworten auf diese Frage zu geben.

(Und ja, ich weiß, dass ich einen Vektor verwenden muss.Dies ist eine dieser Aufgaben vom Typ „C++ nachholen“ in der Schule.)

War es hilfreich?

Lösung

Ja, Sie müssen die Zeiger durchlaufen und einzeln löschen.

Grund:Was wäre, wenn anderer Code Zeiger auf die Objekte in Ihrem Array hätte?Der C++-Compiler weiß nicht, ob das wahr ist oder nicht, also müssen Sie es explizit sagen.

Für einen „einfacheren Weg“ zwei Vorschläge:(1) Erstellen Sie zu diesem Zweck eine Unterroutine, damit Sie den Code zumindest nicht mehr als einmal schreiben müssen.(2) Verwenden Sie das Designparadigma „Smart Pointer“, bei dem Sie ein Array von Objekten mit Referenzzählern speichern und die Objekte dann gelöscht werden, wenn kein Code mehr auf die Objekte verweist.

Andere Tipps

Ich stimme Jason Cohen zu, obwohl wir den Grund für das Löschen Ihrer Zeiger mit der Schleife etwas klarer sagen können.Für jede „neue“ oder dynamische Speicherzuweisung muss ein „Löschen“ bzw. eine Speicherfreigabe erfolgen.Manchmal kann das „Löschen“ ausgeblendet werden, wie bei Smartpointern, aber es ist immer noch da.

int main()
{
  int *pI = new int;
  int *pArr = new int[10];

Bisher haben wir im Code zwei Blöcke dynamischen Speichers zugewiesen.Der erste ist nur ein allgemeiner Int, der zweite ist ein Array von Ints.

  delete pI;
  delete [] pArr;

Diese Löschanweisungen löschen den Speicher, der von den „Neuen“ zugewiesen wurde

  int ppArr = new int *[10];

  for( int indx = 0; indx < 10; ++indx )
  {
    ppArr[indx] = new int;
  }

Dieser Code führt beide vorherigen Zuweisungen durch.Zuerst schaffen wir Platz für unser int in einem dynamischen Array.Anschließend müssen wir eine Schleife durchlaufen und für jede Stelle im Array ein int zuweisen.

  for( int indx = 0; indx < 10; ++indx )
  {
    delete ppArr[indx];
  }
  delete [] ppArr;

Beachten Sie die Reihenfolge, in der ich diesen Speicher zugewiesen und die Zuordnung dann in umgekehrter Reihenfolge aufgehoben habe.Dies liegt daran, dass wir den Befehl delete [] ppArr;Zuerst würden wir das Array verlieren, das uns sagt, was unsere anderen Zeiger sind.Dieser Block oder Speicher würde an das System zurückgegeben und kann daher nicht mehr zuverlässig gelesen werden.

  int a=0;
  int b=1;
  int c=2;

  ppArr = new int *[3];

  ppArr[0] = &a;
  ppArr[1] = &b;
  ppArr[2] = &c;

Das sollte meiner Meinung nach auch erwähnt werden.Nur weil Sie mit Zeigern arbeiten, heißt das nicht, dass der Speicher, auf den diese Zeiger zeigen, dynamisch zugewiesen wurde.Das heißt, nur weil Sie einen Zeiger haben, heißt das nicht, dass er unbedingt gelöscht werden muss.Das hier erstellte Array wird dynamisch zugewiesen, aber die Zeiger zeigen auf lokale Instanzen von ints. Wenn wir dies löschen, müssen wir nur das Array löschen.

  delete [] ppArr;

  return 0;

}

Letztendlich kann es schwierig sein, dynamisch zugewiesenen Speicher zuzuweisen, und Sie können ihn auf jeden Fall sicher in einem Smart Pointer verpacken oder indem Sie statt Ihrer eigenen STL-Container verwenden, kann dies Ihr Leben viel angenehmer machen.

Sehen Boost-Pointer-Container für einen Container, der das automatische Löschen enthaltener Zeiger für Sie übernimmt und dabei eine Syntax beibehält, die der von gewöhnlichen STL-Containern sehr nahe kommt.

Zeiger sind im Grunde nur Speicherreferenzen und keine schicken kleinen selbstreinigenden .net-Objekte.Das Erstellen geeigneter Destruktoren für jede Klasse macht das Löschen etwas sauberer als massive Schleifen im gesamten Code.

Nehmen wir ein (pseudocodiertes) Beispiel aus der realen Welt. Stellen Sie sich vor, Sie hätten eine Klasse wie diese:

class Street
{
    public:
        Street();
        ~Street();
    private:
        int HouseNumbers_[];
}

typedef *Street StreetSign;

Wenn Sie eine Reihe von Straßenschildern haben und diese Reihe von Straßenschildern löschen, bedeutet das nicht, dass Sie die Straßen automatisch löschen.Sie sind immer noch da, Ziegel und Mörtel, es gibt nur keine Hinweisschilder mehr, die auf sie hinweisen.Du bist losgeworden die spezifischen Beispiele für Hinweise auf die Straßen.

Ein Array von Zeigern ist (konzeptionell) ein bisschen wie ein Array von Ganzzahlen, es ist ein Array von Zahlen, die die Speicherorte verschiedener Objekte darstellen.Es sind nicht die Objekte selbst.

Wenn Sie das Zeiger-Array löschen[], löschen Sie lediglich ein Array von Ganzzahlen.

Ich fürchte, Sie werden eine Schleife machen müssen.

Ich weiß nicht, warum darauf so verwirrend lange geantwortet wurde.

Wenn Sie das Array von Zeigern löschen, geben Sie Der Speicher, der für ein Array von normalerweise ints verwendet wird.
Ein Zeiger auf ein Objekt ist eine Ganzzahl, die die Adresse enthält.

Sie haben eine Reihe von Adressen gelöscht, aber keine Objekte.

delete kümmert sich nicht um den Inhalt eines Speicherplatzes, Er ruft einen oder mehrere Destruktor auf und markiert das MEM als frei.

Es kümmert sich nicht darum, dass es gerade einen Haufen Adressen gelöscht hat von Objekten, es sieht lediglich ints.

Deshalb müssen Sie zuerst das Array durchlaufen!und rufen Sie delete auf für jedes Element, dann können Sie den Speicher des Arrays selbst löschen.

Na dann Mein Antwort ist etwas lang geworden.......seltsam...;)

Bearbeiten:Jasons Antwort ist nicht falsch, sie trifft einfach nicht den Punkt.Weder Der Compiler oder irgendetwas anderes in C(++) kümmert sich darum, dass Sie Dinge löschen, die sich an anderer Stelle befinden auf die verwiesen wird.Du kannst es einfach tun.Andere Programmteile, die versuchen, die gelöschten Objekte zu verwenden wird auf dich segfault werden.Aber niemand wird dich behindern.Es ist auch kein Problem, ein Array von Zeigern auf Objekte zu zerstören, wenn die Objekte an anderer Stelle referenziert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top