operator delete , operator delete[]
|
Definiert im Header
<new>
|
||
|
Ersetzbare übliche Freigabefunktionen
|
||
| (1) | ||
|
void
operator delete
(
void
*
ptr
)
throw
(
)
;
|
(bis C++11) | |
|
void
operator delete
(
void
*
ptr
)
noexcept
;
|
(seit C++11) | |
| (2) | ||
|
void
operator delete
[
]
(
void
*
ptr
)
throw
(
)
;
|
(bis C++11) | |
|
void
operator delete
[
]
(
void
*
ptr
)
noexcept
;
|
(seit C++11) | |
|
void
operator delete
(
void
*
ptr,
std::
align_val_t
al
)
noexcept
;
|
(3) | (seit C++17) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
align_val_t
al
)
noexcept
;
|
(4) | (seit C++17) |
|
void
operator delete
(
void
*
ptr,
std::
size_t
sz
)
noexcept
;
|
(5) | (seit C++14) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
size_t
sz
)
noexcept
;
|
(6) | (seit C++14) |
|
void
operator delete
(
void
*
ptr,
std::
size_t
sz,
std:: align_val_t al ) noexcept ; |
(7) | (seit C++17) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
size_t
sz,
std:: align_val_t al ) noexcept ; |
(8) | (seit C++17) |
|
Ersetzbare Platzierungs-Freigabefunktionen
|
||
| (9) | ||
|
void
operator delete
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
throw
(
)
;
|
(bis C++11) | |
|
void
operator delete
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
noexcept
;
|
(seit C++11) | |
| (10) | ||
|
void
operator delete
[
]
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
throw
(
)
;
|
(bis C++11) | |
|
void
operator delete
[
]
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
noexcept
;
|
(seit C++11) | |
|
void
operator delete
(
void
*
ptr,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(11) | (seit C++17) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(12) | (seit C++17) |
|
Nicht-allozierende Platzierungs-Freigabefunktionen
|
||
| (13) | ||
|
void
operator delete
(
void
*
ptr,
void
*
place
)
throw
(
)
;
|
(bis C++11) | |
|
void
operator delete
(
void
*
ptr,
void
*
place
)
noexcept
;
|
(seit C++11) | |
| (14) | ||
|
void
operator delete
[
]
(
void
*
ptr,
void
*
place
)
throw
(
)
;
|
(bis C++11) | |
|
void
operator delete
[
]
(
void
*
ptr,
void
*
place
)
noexcept
;
|
(seit C++11) | |
|
Benutzerdefinierte Platzierungs-Freigabefunktionen
|
||
|
void
operator delete
(
void
*
ptr, args...
)
;
|
(15) | |
|
void
operator delete
[
]
(
void
*
ptr, args...
)
;
|
(16) | |
|
Klassenspezifische übliche Freigabefunktionen
|
||
|
void
T
::
operator
delete
(
void
*
ptr
)
;
|
(17) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr
)
;
|
(18) | |
|
void
T
::
operator
delete
(
void
*
ptr,
std::
align_val_t
al
)
;
|
(19) | (seit C++17) |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
align_val_t
al
)
;
|
(20) | (seit C++17) |
|
void
T
::
operator
delete
(
void
*
ptr,
std::
size_t
sz
)
;
|
(21) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
size_t
sz
)
;
|
(22) | |
|
void
T
::
operator
delete
(
void
*
ptr,
std::
size_t
sz,
std::
align_val_t
al
)
;
|
(23) | (seit C++17) |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
size_t
sz,
std::
align_val_t
al
)
;
|
(24) | (seit C++17) |
|
Klassenspezifische Platzierungs-Freigabefunktionen
|
||
|
void
T
::
operator
delete
(
void
*
ptr, args...
)
;
|
(25) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr, args...
)
;
|
(26) | |
|
Klassenspezifische übliche zerstörende Deallokationsfunktionen
|
||
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
)
;
|
(27) | (seit C++20) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std:: align_val_t al ) ; |
(28) | (seit C++20) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std::
size_t
sz
)
;
|
(29) | (seit C++20) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std:: size_t sz, std:: align_val_t al ) ; |
(30) | (seit C++20) |
Gibt zuvor durch einen passenden operator new oder operator new[] allokierten Speicher frei. Diese Freigabefunktionen werden von delete und delete [ ] Ausdrücken sowie von placement new Ausdrücken aufgerufen, um Speicher nach der Zerstörung (oder fehlgeschlagenen Konstruktion) von Objekten mit dynamischer Speicherdauer freizugeben. Sie können auch über die reguläre Funktionsaufrufsyntax aufgerufen werden.
-
Wenn
ptr
kein Nullzeiger ist und eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
- Für operator delete repräsentiert der Wert von ptr nicht die Adresse eines Speicherblocks, der durch einen vorherigen Aufruf von (möglicherweise ersetztem) operator new ( std:: size_t ) (für Überladungen (1,5,9) ) oder operator new ( std:: size_t , std:: align_val_t ) (für Überladungen (3,7,11) ) zugewiesen wurde, der nicht durch einen zwischenzeitlichen Aufruf von operator delete ungültig gemacht wurde.
- Für operator delete [ ] repräsentiert der Wert von ptr nicht die Adresse eines Speicherblocks, der durch einen vorherigen Aufruf von (möglicherweise ersetztem) operator new [ ] ( std:: size_t ) (für Überladungen (2,6,10) ) oder operator new [ ] ( std:: size_t , std:: align_val_t ) (für Überladungen (4,8,12) ) zugewiesen wurde, der nicht durch einen zwischenzeitlichen Aufruf von operator delete [ ] ungültig gemacht wurde.
Überladungen ( 1-8 ) werden implizit in jeder Übersetzungseinheit deklariert, selbst wenn der <new> Header nicht eingebunden ist.
Siehe delete expression für die Kriterien zur Auswahl der Überladung.
Inhaltsverzeichnis |
Parameter
| ptr | - | Zeiger auf einen freizugebenden Speicherblock oder ein Nullzeiger |
| sz | - | die Größe, die an die passende Allokationsfunktion übergeben wurde |
| place | - | Zeiger, der als Platzierungsparameter im passenden Placement-New verwendet wurde |
| tag | - | Überladungsunterscheidungs-Tag, das zum Tag des nicht-werfenden operator new passt |
| al | - | Ausrichtung des allokierten Objekts oder Array-Elements |
| args | - | beliebige Parameter, die zu einer Platzierungs-Allokationsfunktion passen (können std::size_t und std::align_val_t enthalten) |
Exceptions
|
Alle Freigabefunktionen sind noexcept ( true ) , sofern in der Deklaration nicht anders angegeben. |
(seit C++11) |
Wenn eine Freigabefunktion durch Auslösen einer Exception beendet wird, ist das Verhalten undefiniert , selbst wenn sie mit noexcept ( false ) (seit C++11) deklariert ist.
Globale Ersetzungen
Überladungen ( 1-12 ) sind ersetzbar . Die Effekte der Standardversionen sind:
Globale
operator
-
new
/
delete
-Ersetzung:
#include <cstdio> #include <cstdlib> #include <new> // no inline, required by [replacement.functions]/3 void* operator new(std::size_t sz) { std::printf("1) new(size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } // no inline, required by [replacement.functions]/3 void* operator new[](std::size_t sz) { std::printf("2) new[](size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } void operator delete(void* ptr) noexcept { std::puts("3) delete(void*)"); std::free(ptr); } void operator delete(void* ptr, std::size_t size) noexcept { std::printf("4) delete(void*, size_t), size = %zu\n", size); std::free(ptr); } void operator delete[](void* ptr) noexcept { std::puts("5) delete[](void* ptr)"); std::free(ptr); } void operator delete[](void* ptr, std::size_t size) noexcept { std::printf("6) delete[](void*, size_t), size = %zu\n", size); std::free(ptr); } int main() { int* p1 = new int; delete p1; int* p2 = new int[10]; // guaranteed to call the replacement in C++11 delete[] p2; }
Mögliche Ausgabe:
// Compiled with GCC-5 in C++17 mode to obtain the following: 1) op new(size_t), size = 4 4) op delete(void*, size_t), size = 4 2) op new[](size_t), size = 40 5) op delete[](void* ptr)
Überladungen von operator delete und operator delete [ ] mit zusätzlichen benutzerdefinierten Parametern ("Placement-Formen", ( 15,16 ) ) können wie üblich im globalen Gültigkeitsbereich deklariert werden und werden von den entsprechenden Placement-Formen der new -Ausdrücke aufgerufen, wenn ein Konstruktor des zu allozierenden Objekts eine Exception wirft.
Die Platzierungsformen der Standardbibliothek von operator delete und operator delete [ ] ( 13,14 ) können nicht ersetzt werden und können nur angepasst werden, wenn der Platzierungs- new -Ausdruck nicht die :: new -Syntax verwendet hat, indem ein klassen-spezifischer Platzierungs-delete ( 25,26 ) mit übereinstimmender Signatur bereitgestellt wird: void T :: operator delete ( void * , void * ) oder void T :: operator delete [ ] ( void * , void * ) .
Klassenspezifische Überladungen
Deallocation-Funktionen ( 17-24 ) können als statische Member-Funktionen einer Klasse definiert werden. Diese Deallocation-Funktionen werden, sofern vorhanden, von delete -Ausdrücken beim Löschen von Objekten ( 17,19,21 ) und Arrays ( 18,20,22 ) dieser Klasse aufgerufen, es sei denn, der delete-Ausdruck verwendete die Form :: delete , die die klassenbezogene Suche umgeht. Das Schlüsselwort static ist für diese Funktionsdeklarationen optional: Unabhängig davon, ob das Schlüsselwort verwendet wird oder nicht, ist die Deallocation-Funktion immer eine statische Member-Funktion.
Der delete-Ausdruck sucht nach dem Namen einer geeigneten Freigabefunktion, beginnend im Klassenbereich (die Array-Form sucht im Bereich der Array-Elementklasse) und setzt im globalen Bereich fort, falls keine Member gefunden werden, wie üblich. Beachten Sie, dass gemäß den Namenssuche-Regeln alle im Klassenbereich deklarierten Freigabefunktionen alle globalen Freigabefunktionen verbergen.
Wenn der statische Typ des zu löschenden Objekts von seinem dynamischen Typ abweicht (wie beim Löschen eines polymorphen Objekts durch einen Zeiger auf die Basisklasse), und wenn der Destruktor im statischen Typ virtuell ist, beginnt die Einzelobjekt-Form von delete mit der Suche nach dem Namen der Freigabefunktion ab dem Definitionspunkt des finalen Überschreibers seines virtuellen Destruktors. Unabhängig davon, welche Freigabefunktion zur Laufzeit ausgeführt würde, muss die statisch sichtbare Version von operator delete zugänglich sein, um kompilieren zu können. In anderen Fällen, wenn ein Array durch einen Zeiger auf die Basisklasse gelöscht wird, oder wenn durch einen Zeiger auf die Basisklasse mit nicht-virtuellem Destruktor gelöscht wird, ist das Verhalten undefiniert.
Wenn die Einzelargument-Überladung ( 17,18 ) nicht bereitgestellt wird, aber die größenbewusste Überladung mit std::size_t als zweitem Parameter ( 21,22 ) bereitgestellt wird, wird die größenbewusste Form für die normale Freigabe aufgerufen, und die C++-Laufzeit übergibt die Größe des freizugebenden Objekts als zweites Argument. Wenn beide Formen definiert sind, wird die größenunabhängige Version aufgerufen.
#include <cstddef> #include <iostream> // sized class-specific deallocation functions struct X { static void operator delete(void* ptr, std::size_t sz) { std::cout << "custom delete for size " << sz << '\n'; ::operator delete(ptr); } static void operator delete[](void* ptr, std::size_t sz) { std::cout << "custom delete for size " << sz << '\n'; ::operator delete[](ptr); } }; int main() { X* p1 = new X; delete p1; X* p2 = new X[10]; delete[] p2; }
Mögliche Ausgabe:
custom delete for size 1 custom delete for size 18
Überladungen von operator delete und operator delete [ ] mit zusätzlichen benutzerdefinierten Parametern ("Placement-Formen", ( 25,26 ) ) können ebenfalls als Klassenmember definiert werden. Wenn der fehlgeschlagene Placement- new -Ausdruck nach der entsprechenden Placement- delete -Funktion sucht, um sie aufzurufen, beginnt die Suche im Klassenbereich, bevor der globale Bereich untersucht wird, und sucht nach der Funktion mit der Signatur, die der Placement- new -Funktion entspricht:
#include <cstddef> #include <iostream> #include <stdexcept> struct X { X() { throw std::runtime_error("X(): std::runtime_error"); } // custom placement new static void* operator new(std::size_t sz, bool b) { std::cout << "custom placement new called, b = " << b << '\n'; return ::operator new(sz); } // custom placement delete static void operator delete(void* ptr, bool b) { std::cout << "custom placement delete called, b = " << b << '\n'; ::operator delete(ptr); } }; int main() { try { [[maybe_unused]] X* p1 = new (true) X; } catch (const std::exception& ex) { std::cout << ex.what() << '\n'; } }
Ausgabe:
custom placement new called, b = 1 custom placement delete called, b = 1 X(): std::runtime_error
Wenn der klassenbezogene operator delete eine Template-Funktion ist, muss er den Rückgabetyp void haben, das erste Argument void * , und er muss zwei oder mehr Parameter besitzen. Mit anderen Worten: Nur Placement-Formen können Templates sein. Eine Template-Instanz ist niemals eine übliche Freigabefunktion, unabhängig von ihrer Signatur. Die Spezialisierung des Template-Operator-delete wird mittels Template-Argument-Deduktion ausgewählt.
Hinweise
Der Aufruf des klassen-spezifischen T :: operator delete bei einer polymorphen Klasse ist der einzige Fall, in dem eine statische Memberfunktion durch dynamische Bindung aufgerufen wird.
|
Die folgenden Funktionen müssen thread-sicher sein:
Aufrufe dieser Funktionen, die eine bestimmte Speichereinheit allozieren oder deallozieren, erfolgen in einer einzigen Gesamtordnung, und jeder solche Deallokationsaufruf happens-before dem nächsten Allokationsaufruf (falls vorhanden) in dieser Ordnung. |
(seit C++11) |
| Feature-Test Makro | Wert | Std | Funktion |
|---|---|---|---|
__cpp_sized_deallocation
|
201309L
|
(C++14) | Sized deallocation |
__cpp_impl_destroying_delete
|
201806L
|
(C++20) | Destroying operator delete (Compiler-Unterstützung) |
__cpp_lib_destroying_delete
|
201806L
|
(C++20) | Destroying operator delete (Bibliotheksunterstützung) |
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 220 | C++98 | benutzerdefinierte Freigabefunktionen durften eine Exception werfen |
Werfen einer Exception aus einer Freigabefunktion
führt zu undefiniertem Verhalten |
| CWG 1438 | C++98 | jede Verwendung eines ungültigen Zeigerwerts war undefiniertes Verhalten | nur Dereferenzierung und Freigabe sind |
| LWG 206 | C++98 | Ersetzen von ( 2 ) beeinflusste nicht das Standardverhalten von ( 10 ) |
das Standardverhalten
ändert sich entsprechend |
| LWG 298 | C++98 | Ersetzen von ( 1 ) beeinflusste nicht das Standardverhalten von ( 9 ) |
das Standardverhalten
ändert sich entsprechend |
| LWG 404 | C++98 |
Ersetzungen der ersetzbaren Freigabefunktionen
konnten als inline deklariert werden |
verboten, keine Diagnose erforderlich |
| LWG 2458 | C++14 |
Überladungen mit
(
void
*
,
std::
size_t
,
const
std:: nothrow_t & ) waren spezifiziert, konnten aber nie aufgerufen werden |
entfernte überflüssige Überladungen |
Siehe auch
|
[static]
(C++23)
|
gibt zuvor von
operator new
beschafften Speicher frei
(öffentliche statische Mitgliedsfunktion von
std::generator<Ref,V,Allocator>::promise_type
)
|
|
Allokierungsfunktionen
(Funktion) |
|
|
(in C++17 veraltet)
(in C++20 entfernt)
|
gibt nicht initialisierten Speicher frei
(Funktionsschablone) |
|
gibt zuvor allokierten Speicher frei
(Funktion) |