operator delete , operator delete[]
|
Défini dans l'en-tête
<new>
|
||
|
Fonctions de désallocation usuelles remplaçables
|
||
| (1) | ||
|
void
operator delete
(
void
*
ptr
)
throw
(
)
;
|
(jusqu'à C++11) | |
|
void
operator delete
(
void
*
ptr
)
noexcept
;
|
(depuis C++11) | |
| (2) | ||
|
void
operator delete
[
]
(
void
*
ptr
)
throw
(
)
;
|
(jusqu'à C++11) | |
|
void
operator delete
[
]
(
void
*
ptr
)
noexcept
;
|
(depuis C++11) | |
|
void
operator delete
(
void
*
ptr,
std::
align_val_t
al
)
noexcept
;
|
(3) | (depuis C++17) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
align_val_t
al
)
noexcept
;
|
(4) | (depuis C++17) |
|
void
operator delete
(
void
*
ptr,
std::
size_t
sz
)
noexcept
;
|
(5) | (depuis C++14) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
size_t
sz
)
noexcept
;
|
(6) | (depuis C++14) |
|
void
operator delete
(
void
*
ptr,
std::
size_t
sz,
std:: align_val_t al ) noexcept ; |
(7) | (depuis C++17) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
size_t
sz,
std:: align_val_t al ) noexcept ; |
(8) | (depuis C++17) |
|
Fonctions de désallocation de placement remplaçables
|
||
| (9) | ||
|
void
operator delete
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
throw
(
)
;
|
(jusqu'à C++11) | |
|
void
operator delete
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
noexcept
;
|
(depuis C++11) | |
| (10) | ||
|
void
operator delete
[
]
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
throw
(
)
;
|
(jusqu'à C++11) | |
|
void
operator delete
[
]
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
noexcept
;
|
(depuis C++11) | |
|
void
operator delete
(
void
*
ptr,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(11) | (depuis C++17) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(12) | (depuis C++17) |
|
Fonctions de désallocation de placement non-allouantes
|
||
| (13) | ||
|
void
operator delete
(
void
*
ptr,
void
*
place
)
throw
(
)
;
|
(jusqu'à C++11) | |
|
void
operator delete
(
void
*
ptr,
void
*
place
)
noexcept
;
|
(depuis C++11) | |
| (14) | ||
|
void
operator delete
[
]
(
void
*
ptr,
void
*
place
)
throw
(
)
;
|
(jusqu'à C++11) | |
|
void
operator delete
[
]
(
void
*
ptr,
void
*
place
)
noexcept
;
|
(depuis C++11) | |
|
Fonctions de désallocation de placement définies par l'utilisateur
|
||
|
void
operator delete
(
void
*
ptr, args...
)
;
|
(15) | |
|
void
operator delete
[
]
(
void
*
ptr, args...
)
;
|
(16) | |
|
Fonctions de désallocation usuelles spécifiques à la classe
|
||
|
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) | (depuis C++17) |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
align_val_t
al
)
;
|
(20) | (depuis 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) | (depuis C++17) |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
size_t
sz,
std::
align_val_t
al
)
;
|
(24) | (depuis C++17) |
|
Fonctions de désallocation placement spécifiques à la classe
|
||
|
void
T
::
operator
delete
(
void
*
ptr, args...
)
;
|
(25) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr, args...
)
;
|
(26) | |
|
Fonctions de désallocation de destruction habituelles spécifiques à la classe
|
||
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
)
;
|
(27) | (depuis C++20) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std:: align_val_t al ) ; |
(28) | (depuis C++20) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std::
size_t
sz
)
;
|
(29) | (depuis C++20) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std:: size_t sz, std:: align_val_t al ) ; |
(30) | (depuis C++20) |
Libère le stockage précédemment alloué par un operator new ou un operator new[] correspondant. Ces fonctions de libération sont appelées par les delete et delete [ ] expressions et par les placement new expressions pour libérer la mémoire après la destruction (ou l'échec de construction) d'objets ayant une durée de stockage dynamique. Elles peuvent également être appelées en utilisant la syntaxe d'appel de fonction classique.
-
Si
ptr
n'est pas un pointeur nul et qu'une des conditions suivantes est satisfaite, le comportement est indéfini :
- Pour operator delete , la valeur de ptr ne représente pas l'adresse d'un bloc de mémoire alloué par un appel antérieur à (éventuellement remplacé) operator new ( std:: size_t ) (pour les surcharges (1,5,9) ) ou operator new ( std:: size_t , std:: align_val_t ) (pour les surcharges (3,7,11) ) qui n'a pas été invalidé par un appel intermédiaire à operator delete .
- Pour operator delete [ ] , la valeur de ptr ne représente pas l'adresse d'un bloc de mémoire alloué par un appel antérieur à (éventuellement remplacé) operator new [ ] ( std:: size_t ) (pour les surcharges (2,6,10) ) ou operator new [ ] ( std:: size_t , std:: align_val_t ) (pour les surcharges (4,8,12) ) qui n'a pas été invalidé par un appel intermédiaire à operator delete [ ] .
Surcharges ( 1-8 ) sont implicitement déclarées dans chaque unité de traduction même si l'en-tête <new> n'est pas inclus.
Voir delete expression pour les critères de sélection de surcharge.
Table des matières |
Paramètres
| ptr | - | pointeur vers un bloc mémoire à désallouer ou un pointeur nul |
| sz | - | la taille qui a été passée à la fonction d'allocation correspondante |
| place | - | pointeur utilisé comme paramètre de placement dans le placement new correspondant |
| tag | - | balise de désambiguïsation de surcharge correspondant à celle utilisée par l'opérateur new non-lançant |
| al | - | alignement de l'objet ou de l'élément de tableau qui a été alloué |
| args | - | paramètres arbitraires correspondant à une fonction d'allocation de placement (peut inclure std::size_t et std::align_val_t ) |
Exceptions
|
Toutes les fonctions de désallocation sont noexcept ( true ) sauf indication contraire dans la déclaration. |
(depuis C++11) |
Si une fonction de désallocation se termine en lançant une exception, le comportement est indéfini , même si elle est déclarée avec noexcept ( false ) (depuis C++11) .
Remplacements globaux
Surcharges ( 1-12 ) sont remplaçables . Les effets des versions par défaut sont :
Opérateurs globaux
operator
de remplacement
new
/
delete
:
#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; }
Sortie possible :
// 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)
Les surcharges de operator delete et operator delete [ ] avec des paramètres supplémentaires définis par l'utilisateur ("formes de placement", ( 15,16 ) ) peuvent être déclarées au niveau global comme d'habitude, et sont appelées par les formes de placement correspondantes des expressions new si un constructeur de l'objet en cours d'allocation lève une exception.
Les formes de placement de la bibliothèque standard de operator delete et de operator delete [ ] ( 13,14 ) ne peuvent pas être remplacées et ne peuvent être personnalisées que si l'expression de placement new n'a pas utilisé la syntaxe :: new , en fournissant un placement delete spécifique à la classe ( 25,26 ) avec une signature correspondante : void T :: operator delete ( void * , void * ) ou void T :: operator delete [ ] ( void * , void * ) .
Surcharges spécifiques à la classe
Fonctions de désallocation ( 17-24 ) peuvent être définies comme fonctions membres statiques d'une classe. Ces fonctions de désallocation, si elles sont fournies, sont appelées par les expressions delete lors de la suppression d'objets ( 17,19,21 ) et de tableaux ( 18,20,22 ) de cette classe, sauf si l'expression delete a utilisé la forme :: delete qui contourne la recherche dans la portée de la classe. Le mot-clé static est optionnel pour ces déclarations de fonctions : que le mot-clé soit utilisé ou non, la fonction de désallocation est toujours une fonction membre statique.
L'expression delete recherche le nom de la fonction de désallocation appropriée en commençant par la portée de la classe (la forme tableau recherche dans la portée de la classe des éléments du tableau) et procède à la portée globale si aucun membre n'est trouvé comme d'habitude. Notez que, conformément aux règles de recherche de nom , toute fonction de désallocation déclarée dans la portée de la classe masque toutes les fonctions de désallocation globales.
Si le type statique de l'objet en cours de suppression diffère de son type dynamique (comme lors de la suppression d'un objet polymorphe via un pointeur vers la base), et si le destructeur dans le type statique est virtuel, la forme à objet unique de delete commence la recherche du nom de la fonction de désallocation à partir du point de définition du remplacement final de son destructeur virtuel. Quelle que soit la fonction de désallocation qui serait exécutée à l'exécution, la version statiquement visible de operator delete doit être accessible pour permettre la compilation. Dans les autres cas, lors de la suppression d'un tableau via un pointeur vers la base, ou lors de la suppression via un pointeur vers la base avec un destructeur non virtuel, le comportement est indéfini.
Si la surcharge à un seul argument ( 17,18 ) n'est pas fournie, mais que la surcharge prenant en compte la taille avec std::size_t comme second paramètre ( 21,22 ) est fournie, la forme prenant en compte la taille est appelée pour la désallocation normale, et l'environnement d'exécution C++ passe la taille de l'objet à désallouer comme second argument. Si les deux formes sont définies, la version ne prenant pas en compte la taille est appelée.
#include <cstddef> #include <iostream> // fonctions de désallocation dimensionnées spécifiques à la classe 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; }
Sortie possible :
custom delete for size 1 custom delete for size 18
Les surcharges de operator delete et operator delete [ ] avec des paramètres supplémentaires définis par l'utilisateur ("formes de placement", ( 25,26 ) ) peuvent également être définies comme membres de classe. Lorsque l'expression de placement new échoué recherche la fonction de placement delete correspondante à appeler, elle commence la recherche dans la portée de la classe avant d'examiner la portée globale, et recherche la fonction dont la signature correspond au placement new :
#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'; } }
Sortie :
custom placement new called, b = 1 custom placement delete called, b = 1 X(): std::runtime_error
Si l'opérateur delete au niveau de la classe operator delete est une fonction template, il doit avoir le type de retour void , le premier argument void * , et il doit avoir deux paramètres ou plus. En d'autres termes, seules les formes de placement peuvent être des templates. Une instance de template n'est jamais une fonction de désallocation usuelle, quelle que soit sa signature. La spécialisation du template operator delete est choisie avec la déduction d'arguments template .
Notes
L'appel à la fonction spécifique à la classe T :: operator delete sur une classe polymorphe est le seul cas où une fonction membre statique est appelée via une dispatch dynamique.
|
Les fonctions suivantes doivent être thread-safe :
Les appels à ces fonctions qui allouent ou désallouent une unité de stockage particulière se produisent dans un ordre total unique, et chaque appel de désallocation se produit-avant la prochaine allocation (le cas échéant) dans cet ordre. |
(depuis C++11) |
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_sized_deallocation
|
201309L
|
(C++14) | Désallocation dimensionnée |
__cpp_impl_destroying_delete
|
201806L
|
(C++20) | Opérateur delete destructeur (support du compilateur) |
__cpp_lib_destroying_delete
|
201806L
|
(C++20) | Opérateur delete destructeur (support de la bibliothèque) |
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement tel que publié | Comportement correct |
|---|---|---|---|
| CWG 220 | C++98 | les fonctions de désallocation définies par l'utilisateur pouvaient lever des exceptions |
lever une exception depuis une fonction de désallocation
entraîne un comportement indéfini |
| CWG 1438 | C++98 | toute utilisation d'une valeur de pointeur invalide était un comportement indéfini | seules l'indirection et la désallocation le sont |
| LWG 206 | C++98 | le remplacement de ( 2 ) n'affectait pas le comportement par défaut de ( 10 ) |
le comportement par défaut
change en conséquence |
| LWG 298 | C++98 | le remplacement de ( 1 ) n'affectait pas le comportement par défaut de ( 9 ) |
le comportement par défaut
change en conséquence |
| LWG 404 | C++98 |
les remplacements des fonctions de désallocation remplaçables
pouvaient être déclarés inline |
interdit, aucun diagnostic requis |
| LWG 2458 | C++14 |
les surcharges prenant
(
void
*
,
std::
size_t
,
const
std:: nothrow_t & ) étaient spécifiées, mais ne pouvaient jamais être appelées |
surcharges superflues supprimées |
Voir aussi
|
[static]
(C++23)
|
désalloue la mémoire précédemment obtenue de
operator new
(fonction membre statique publique de
std::generator<Ref,V,Allocator>::promise_type
)
|
|
fonctions d'allocation
(fonction) |
|
|
(obsolète en C++17)
(supprimé en C++20)
|
libère le stockage non initialisé
(fonction template) |
|
désalloue la mémoire précédemment allouée
(fonction) |