delete-Ausdruck
Zerstört durch den new-Ausdruck zuvor zugewiesene Objekte und gibt den belegten Speicherbereich frei.
Inhalt |
[edit] Syntax
::(optional) delete Ausdruck |
(1) | ||||||||
::(optional) delete[] Ausdruck |
(2) | ||||||||
| expression | - | einer der folgenden
|
[edit] Erläuterung
Gegeben sei der durch Ausdruck ausgewertete Zeiger (nach möglichen Konvertierungen) als ptr.
- ein Nullzeiger,
- ein Zeiger auf ein Nicht-Array-Objekt, das durch einen new-Ausdruck erzeugt wurde, oder
- ein Zeiger auf ein Basis-Subobjekt eines Nicht-Array-Objekts, das durch einen new-Ausdruck erzeugt wurde.
Das Ergebnis des delete-Ausdrucks hat immer den Typ void.
Wenn das zu löschende Objekt zum Zeitpunkt der Löschung einen unvollständigen Klassentyp hat, und die vollständige Klasse einen nicht-trivialen Destruktor oder eine Deallokationsfunktion hat, ist das Verhalten undefiniert(bis C++26)ist das Programm schlecht formuliert(seit C++26).
Wenn ptr kein Nullzeiger istund die Deallokationsfunktion kein löschender delete ist(seit C++20), ruft der delete-Ausdruck den Destruktor (falls vorhanden) für das zu zerstörende Objekt auf, oder für jedes Element des zu zerstörenden Arrays (beginnend beim letzten Element bis zum ersten). Der Destruktor muss von dem Punkt an, an dem der delete-Ausdruck erscheint, zugänglich sein.
Danach ruft der delete-Ausdruck, unabhängig davon, ob ein Destruktor eine Ausnahme ausgelöst hat, die Deallokationsfunktion auf: entweder operator delete (erste Version) oder operator delete[] (zweite Version), es sei denn, der passende new-Ausdruck wurde mit einem anderen new-Ausdruck kombiniert(seit C++14).
Der Name der Deallokationsfunktion wird im Gültigkeitsbereich des dynamischen Typs des von ptr gezeigten Objekts nachgeschlagen, was bedeutet, dass klassenspezifische Deallokationsfunktionen, falls vorhanden, vor den globalen gefunden werden. Wenn :: im delete-Ausdruck vorhanden ist, wird durch diese Suche nur der globale Namensraum untersucht. In jedem Fall werden alle Deklarationen, die keine üblichen Deallokationsfunktionen sind, verworfen.
Wenn eine Deallokationsfunktion gefunden wird, wird die aufzurufende Funktion wie folgt ausgewählt (siehe Deallokationsfunktion für eine detailliertere Beschreibung dieser Funktionen und ihrer Auswirkungen)
|
(seit C++20) |
|
(seit C++17) |
- Wenn die gefundenen Deallokationsfunktionen klassenspezifisch sind, wird eine klassenspezifische Deallokationsfunktion ohne Größeninformation (ohne Parameter vom Typ std::size_t) gegenüber einer klassenspezifischen Deallokationsfunktion mit Größeninformation (mit Parameter vom Typ std::size_t) bevorzugt.
|
(seit C++14) |
Die ausgewählte Deallokationsfunktion muss von dem Punkt an, an dem der delete-Ausdruck erscheint, zugänglich sein, es sei denn, die Deallokationsfunktion wird an der Punktdefinition des dynamischen Typs des virtuellen Destruktors ausgewählt.
Der Zeiger auf den wiederzugewinnenden Speicherblock wird als erstes Argument an die Deallokationsfunktion übergeben, die durch den obigen Prozess ausgewählt wurde. Die Größe des Blocks wird als optionales std::size_t-Argument übergeben. Die Ausrichtungsanforderung wird als optionales std::align_val_t-Argument übergeben.(seit C++17)
Wenn ptr ein Nullzeigerwert ist, werden keine Destruktoren aufgerufen, und die Deallokationsfunktion kann aufgerufen werden oder auch nicht (es ist nicht spezifiziert), aber die Standard-Deallokationsfunktionen garantieren, dass sie nichts tun, wenn sie mit einem Nullzeiger aufgerufen werden.
Wenn ptr ein Zeiger auf ein Basisklassen-Subobjekt des mit new alloziierten Objekts ist, muss der Destruktor der Basisklasse virtuell sein, andernfalls ist das Verhalten undefiniert.
[edit] Anmerkungen
Ein Zeiger auf void kann nicht gelöscht werden, da es kein Zeiger auf einen Objekttyp ist.
|
Da ein Paar Klammern nach dem Schlüsselwort delete immer als die Array-Form eines delete-Ausdrucks interpretiert wird, muss ein Lambda-Ausdruck mit leerer Capture-Liste unmittelbar nach delete in Klammern gesetzt werden. // delete []{ return new int; }(); // parse error delete ([]{ return new int; })(); // OK |
(seit C++11) |
[edit] Schlüsselwörter
[edit] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 288 | C++98 | für die erste Form wurde der statische Typ des Operanden mit seinem dynamischen Typ verglichen |
vergleiche den statischen Typ des Objekts das gelöscht werden soll, mit seinem dynamischen Typ |
| CWG 353 | C++98 | ob die Deallokationsfunktion aufgerufen wird, wenn der Destruktor eine Ausnahme auslöst, war nicht spezifiziert |
wird immer aufgerufen |
| CWG 599 | C++98 | die erste Form konnte einen Nullzeiger von jedem Typ, einschließlich Funktionszeigern, |
außer Zeigern auf Objekttypen, annehmen alle anderen Zeigertypen werden abgelehnt |
| CWG 1642 | C++98 | Ausdruck könnte ein Zeiger-Lvalue sein | nicht erlaubt |
| CWG 2474 | C++98 | das Löschen eines Zeigers auf ein Objekt eines ähnlichen, aber anderen Typs führte zu undefiniertem Verhalten |
wurde wohlformuliert |
| CWG 2624 | C++98 | von nicht-allozierenden operator new[] erhaltene Zeiger konnten an delete[] übergeben werden |
verboten |
| CWG 2758 | C++98 | es war unklar, wie die Zugriffskontrolle für die Deallokationsfunktion und den Destruktor gehandhabt wurde |
wurde klargestellt |