Array von Strukturen und new / delete

7

Ich habe eine Struktur wie folgt:

%Vor%

Sagen wir, ich möchte ein Element wie folgt löschen:

%Vor%

Und ich habe später an derselben Stelle ein neues Objekt erstellt:

%Vor%

Würde ich noch delete[] aufrufen müssen, um das zu bereinigen? Oder wird dies nicht benötigt, da die Grenzen des Arrays items[] vor dem Kompilieren bekannt sind?

Setzen Sie diesen Zeiger auf NULL gültig oder soll ich dort löschen aufrufen?

    
Daniel Sloof 12.01.2009, 00:53
quelle

8 Antworten

15

Sie müssen delete aufrufen, bevor Sie NULL setzen. (Das Setzen auf NULL ist nicht erforderlich, es hilft nur, Fehler zu reduzieren, wenn Sie versehentlich versuchen, den Zeiger nach dem Löschen zu dereferenzieren.)

Denken Sie daran, dass Sie jedes Mal, wenn Sie new verwenden, delete später für denselben Zeiger verwenden müssen. Niemals eins ohne das andere benutzen.

Auch new [] und delete [] gehen auf die gleiche Weise zusammen, aber Sie sollten niemals new [] mit delete oder new mit delete [] mischen. Da Sie in Ihrem Beispiel das Objekt mit new erstellt haben (anstatt new [] , das ein Array von Objekten erstellen würde), müssen Sie das Objekt mit delete (statt delete [] ) löschen.

    
Jeremy Ruten 12.01.2009, 01:04
quelle
6

Kluge wies darauf hin, dass Sie das Objekt bei Index 5 so verlieren würden. Aber dieses klingt wirklich so, als ob Sie das nicht manuell tun sollten, sondern eine Container-Klasse innerhalb von Item verwenden sollten. Wenn Sie diese item -Objekte nicht wirklich als Zeiger speichern müssen, verwenden Sie std::vector<item> anstelle dieses Arrays von MAX_ITEMS -Zeigern. Sie können auch jederzeit Vektorelemente in der Mitte einfügen oder löschen.

Falls Sie die Objekte als Zeiger speichern müssen (normalerweise wenn struct item tatsächlich polymorph ist, anders als in Ihrem Beispiel), können Sie boost :: ptr_vector & lt; item & gt; von Boost.PtrContainer statt.

Beispiel:

%Vor%     
Pyry Jahkola 12.01.2009 01:13
quelle
1

Um einen Gegenstand zu löschen, benutzen Sie:

Elemente löschen [5];

Nach dem Löschen des Elements ist es ratsam, den gelöschten Zeiger auf NULL zu setzen, damit Sie keinen Fehler haben, wenn Sie ihn später versehentlich wieder löschen.

Elemente [5] = NULL

    
Joao Vilaca 12.01.2009 01:14
quelle
1
  

Sagen wir, ich möchte ein Element wie folgt löschen:

     
    

Elemente [5] = NULL;

  

Ich kenne wenig Visual Basic, aber das riecht nach einem Visual Basic-Programmier-Idiom, da "Set a = None" (oder Null, ich bin nicht sicher) das Objekt, das auf a zeigt, löscht (oder eher seinen Referenzzähler dekrementiert) , für COM-Objekte).

Wie jemand anders bemerkt hat, sollten Sie entweder:

verwenden %Vor%

oder:

%Vor%

Nach delete[5] verursacht die einzige mögliche Verwendung des in items[5] gespeicherten Zeigers Probleme. Was noch schlimmer ist, ist, dass es am Anfang funktioniert und nur dann einen Fehler verursacht, wenn Sie etwas anderes über den zuvor von *items[5] verwendeten Platz zuweisen. Das sind die Gründe, die C / C ++ - Programmierung "interessant" machen, d. H. Wirklich nervig (sogar für diejenigen, die C mögen wie ich).

Das Schreiben von delete items[5]; speichert, was ein nutzloser Schreibvorgang sein kann, aber das ist eine vorzeitige Optimierung.

    
Blaisorblade 12.01.2009 01:50
quelle
1

Nur um klar zu sein: Sie beziehen sich auf den Aufruf von " delete[] ". Ich denke du meinst delete .

Ich erwähne das, weil C ++ zwei getrennte Operatoren hat, operator delete und operator delete[] . Letzteres wird zum Löschen von Arrays von Objekten verwendet, die mit operator new[] zugewiesen wurden, und gilt in diesem Fall nicht . Sie haben ein Array von -Zeigern auf -Objekte, die Sie mit wiederholten Aufrufen von operator new initialisiert haben müssen, anstatt mit einem einzelnen Aufruf von operator new[] .

Alles was ich wirklich sagen will ist: Ihre Verwendung von delete[] ist verwirrend und mehrdeutig; ändere es in delete .

    
j_random_hacker 12.01.2009 08:07
quelle
1

Es gibt einige verwandte Fragen hier:

  1. Gemäß dem von Ihnen geposteten Code wird das Array selbst nicht auf dem Heap zugeordnet, es sei denn struct ist, sodass Sie delete[] nicht benötigen. Wenn Sie das Array mit new[] erstellt haben, müssten Sie delete[] it.
  2. eingeben
  3. Der angegebene Code sagt nicht, wie die Objekte, auf die vom Array aus verwiesen wird, zugeordnet sind. Wenn Sie diese Objekte auf dem Stack zuweisen, dürfen Sie sie nicht löschen (das ist auch sehr unwahrscheinlich, da Ihre Zeiger ungültig werden, wenn die Objekte, auf die sie verweisen, nicht in den Geltungsbereich fallen). Wenn Sie sie auf dem Heap (mit new) zugewiesen haben, müssen Sie sie löschen, wenn sie außerhalb des Gültigkeitsbereichs liegen.
  4. Wie andere bereits angedeutet haben, ist das Leben viel einfacher, wenn Sie einen Container verwenden - insbesondere einen STL-Container - und intelligente Zeiger - was im Moment Boost-Pointer bedeutet.
Max Lybbert 23.12.2009 09:18
quelle
0

C ++ ist nicht meine Stärke, aber ich bin mir ziemlich sicher, dass Sie den Speicher verlieren würden, wenn Sie den Zeiger auf NULL setzen.

EDIT: Der ausgelaufene Speicher ist der Speicher, auf den der Zeiger im Array zeigt.

    
Hank Gay 12.01.2009 00:57
quelle
0

Das Einstellen von Elementen [5] auf NULL löscht nicht den mit dem Element verbundenen Speicher, sondern setzt den Zeiger auf dieses Element auf NULL, weshalb der Speicher leckt.

Sie können das Element löschen, indem Sie Folgendes aufrufen:

%Vor%

Da C ++ keine automatische Speicherbereinigung hat, müssen Sie jeden Speicher löschen, den Sie nicht mehr benötigen.

    
Kluge 12.01.2009 00:59
quelle