Namespaces
Variants

operator delete , operator delete[]

From cppreference.net
< cpp ‎ | memory ‎ | new
Utilities library
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
**Anmerkung:** Der C++-Code wurde gemäß den Anforderungen nicht übersetzt. Die einzige übersetzbare Textkomponente "(21)" wurde beibehalten, da es sich um eine Versionsnummer handelt, die in technischer Dokumentation typischerweise nicht übersetzt wird. (Anmerkung: Der bereitgestellte HTML-Code enthält keinen übersetzbaren Text, da alle Tags und Attribute gemäß den Anweisungen unverändert bleiben sollen und die Tabellenzellen leer sind.)
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.

1-12) Ersetzbare Freigabefunktionen. Die Standardbibliothek stellt Standardimplementierungen für diese Funktionen bereit, für die Effekte der Standardimplementierungen siehe unten .
1-8) Aufgerufen von delete - und delete [ ] -Ausdrücken. Macht jeden nicht-null ptr ungültig.
9-12) Wird von Placement- new -Ausdrücken bei Initialisierungsfehlern aufgerufen. operator delete [ ] macht jeden nicht-null ptr ungültig.
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.
13,14) Wird von Placement- new -Ausdrücken aufgerufen, die die nicht-allozierende Placement-Allokationsfunktion aufgerufen haben, wenn irgendein Teil der Initialisierung im Ausdruck durch Auslösen einer Exception beendet wird. Führt keine Aktion aus.
15-30) Benutzerdefinierte Freigabefunktionen, aufgerufen durch delete , delete [ ] und Placement- new -Ausdrücke.
27-30) Falls definiert, delete -Ausdrücke führen den Destruktor für * ptr nicht vor dem Aufruf von operator delete aus. Stattdessen wird die direkte Aufrufung des Destruktors, wie durch ptr - > ~T ( ) ; , zur Verantwortung dieses operator delete .

Ü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:

1) Wenn ptr null ist, tut nichts. Andernfalls gibt den Speicher frei, der durch den vorherigen Aufruf von operator new alloziert wurde.
2) Ruft operator delete ( ptr ) auf, als ob Überladung (1) den durch den vorherigen Aufruf von operator new [ ] allokierten Speicher zurückgewinnen könnte.
3) Gleich wie (1) .
4) Ruft operator delete ( ptr, al ) auf, als ob Überladung (3) den durch den vorherigen Aufruf von operator new [ ] allokierten Speicher freigeben könnte.
5) Ruft operator delete ( ptr ) auf.
6) Ruft operator delete [ ] ( ptr ) auf.
7) Ruft operator delete ( ptr, al ) auf.
8) Ruft operator delete [ ] ( ptr, al ) auf.
9) Ruft operator delete ( ptr ) auf.
10) Ruft operator delete [ ] ( ptr ) auf.
11) Ruft operator delete ( ptr, al ) auf.
12) Ruft operator delete [ ] ( ptr, al ) auf.

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)