operator new , operator new[]
|
Défini dans l'en-tête
<new>
|
||
|
Fonctions d'allocation remplaçables
|
||
|
void
*
operator new
(
std::
size_t
count
)
;
|
(1) | |
|
void
*
operator new
[
]
(
std::
size_t
count
)
;
|
(2) | |
|
void
*
operator new
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(3) | (depuis C++17) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(4) | (depuis C++17) |
|
Fonctions d'allocation remplaçables non levantes
|
||
|
void
*
operator new
(
std::
size_t
count,
const
std::
nothrow_t
&
tag
)
;
|
(5) | (noexcept depuis C++11) |
|
void
*
operator new
[
]
(
std::
size_t
count,
const
std::
nothrow_t
&
tag
)
;
|
(6) | (noexcept depuis C++11) |
|
void
*
operator new
(
std::
size_t
count,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(7) | (depuis C++17) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(8) | (depuis C++17) |
|
Fonctions d'allocation de placement sans allocation
|
||
|
void
*
operator new
(
std::
size_t
count,
void
*
ptr
)
;
|
(9) |
(noexcept depuis C++11)
(constexpr depuis C++26) |
|
void
*
operator new
[
]
(
std::
size_t
count,
void
*
ptr
)
;
|
(10) |
(noexcept depuis C++11)
(constexpr depuis C++26) |
|
Fonctions d'allocation de placement définies par l'utilisateur
|
||
|
void
*
operator new
(
std::
size_t
count,
/* args... */
)
;
|
(11) | |
|
void
*
operator new
[
]
(
std::
size_t
count,
/* args... */
)
;
|
(12) | |
|
void
*
operator new
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(13) | (depuis C++17) |
|
void
*
operator new
[
]
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(14) | (depuis C++17) |
|
Fonctions d'allocation spécifiques à la classe
|
||
|
void
*
T
::
operator
new
(
std::
size_t
count
)
;
|
(15) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count
)
;
|
(16) | |
|
void
*
T
::
operator
new
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(17) | (depuis C++17) |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
std::
align_val_t
al
)
;
|
(18) | (depuis C++17) |
|
Fonctions d'allocation placement spécifiques à la classe
|
||
|
void
*
T
::
operator
new
(
std::
size_t
count,
/* args... */
)
;
|
(19) | |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
/* args... */
)
;
|
(20) | |
|
void
*
T
::
operator
new
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(21) | (depuis C++17) |
|
void
*
T
::
operator
new
[
]
(
std::
size_t
count,
std:: align_val_t al, /* args... */ ) ; |
(22) | (depuis C++17) |
Tente d'allouer le nombre demandé d'octets, et la demande d'allocation peut échouer (même si le nombre demandé d'octets est zéro). Ces fonctions d'allocation sont appelées par les new expressions pour allouer la mémoire dans laquelle le nouvel objet serait ensuite initialisé. Elles peuvent également être appelées en utilisant la syntaxe normale d'appel de fonction.
Surcharges ( 1-4 ) sont implicitement déclarées dans chaque unité de traduction même si l'en-tête <new> n'est pas inclus.
Voir new expression pour les critères de sélection de surcharge.
Table des matières |
Paramètres
| count | - | nombre d'octets à allouer |
| ptr | - | pointeur vers une zone mémoire pour initialiser l'objet |
| tag | - | étiquette de désambiguïsation utilisée pour sélectionner les surcharges non levantes |
| al | - | alignement à utiliser, une valeur non valide conduit à un comportement indéfini |
Valeur de retour
Exceptions
Remplacements globaux
Surcharges ( 1-8 ) sont remplaçables . Les effets des versions par défaut sont :
- Si la tentative réussit, retourne un pointeur vers le stockage alloué.
- Sinon, si actuellement aucun new-handler n'est installé, lance std::bad_alloc .
-
Sinon, appelle le new-handler actuellement installé.
- Si le new-handler retourne, commence une nouvelle tentative d'allocation.
- Sinon, termine l'invocation actuelle.
- Si l'appel se termine normalement, retourne le résultat de cet appel.
- Sinon, retourne un pointeur nul.
|
Sur les implémentations freestanding , il est défini par l'implémentation si les versions par défaut de ( 1-8 ) satisfont les comportements requis ci-dessus. Il est recommandé que si l'une de ces versions par défaut répond aux exigences d'une implémentation hébergée, elles le fassent toutes. |
(since C++26) |
Opérateurs globaux
operator
new
/
delete
de remplacement :
#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 new
et
operator new[]
avec des paramètres supplémentaires définis par l'utilisateur ("formes de placement", versions
(
11-14
)
) peuvent être déclarées au niveau global comme d'habitude, et sont appelées par les
formes de placement
correspondantes des expressions
new
.
Les formes de placement non-allouantes de la bibliothèque standard de
operator new
(
9,10
)
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 spécifique à la classe
new
(
19,20
)
avec la signature correspondante :
void
*
T
::
operator
new
(
std::
size_t
,
void
*
)
ou
void
*
T
::
operator
new
[
]
(
std::
size_t
,
void
*
)
.
|
La forme de placement void * operator new ( std:: size_t , std:: size_t ) n'est pas autorisée car la signature correspondante de la fonction de désallocation, void operator delete ( void * , std:: size_t ) , est une fonction de désallocation usuelle (non de placement). |
(depuis C++14) |
Surcharges spécifiques à la classe
Les fonctions d'allocation pour un objet unique et pour un tableau peuvent être définies comme des fonctions membres statiques publiques d'une classe (versions ( 15-18 ) ). Si elles sont définies, ces fonctions d'allocation sont appelées par les expressions new pour allouer de la mémoire pour des objets uniques et des tableaux de cette classe, sauf si l'expression new a utilisé la forme :: new qui contourne la recherche dans la portée de la classe. Le mot-clé static est optionnel pour ces fonctions : qu'il soit utilisé ou non, la fonction d'allocation est une fonction membre statique.
L'expression new recherche d'abord le nom de la fonction d'allocation appropriée dans la portée de la classe, puis dans la portée globale. Notez que, conformément aux règles de recherche de nom , toute fonction d'allocation déclarée dans la portée de la classe masque toutes les fonctions d'allocation globales pour les expressions new qui tentent d'allouer des objets de cette classe.
|
Lors de l'allocation d'objets et de tableaux d'objets dont l'alignement dépasse __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la résolution de surcharge est effectuée deux fois : d'abord pour les signatures de fonctions prenant en compte l'alignement, puis pour les signatures de fonctions ignorant l'alignement. Cela signifie que si une classe avec un alignement étendu possède une fonction d'allocation spécifique à la classe ignorant l'alignement, c'est cette fonction qui sera appelée, et non la fonction d'allocation globale prenant en compte l'alignement. Ce comportement est intentionnel : on attend que le membre de classe sache mieux comment gérer cette classe. |
(depuis C++17) |
|
Lors de l'allocation d'objets et de tableaux d'objets dont l'alignement ne dépasse pas __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la résolution de surcharge est effectuée deux fois : d'abord pour les signatures de fonctions non sensibles à l'alignement, puis pour les signatures de fonctions sensibles à l'alignement. |
(depuis C++20) |
#include <cstddef> #include <iostream> // class-specific allocation functions struct X { static void* operator new(std::size_t count) { std::cout << "custom new for size " << count << '\n'; return ::operator new(count); } static void* operator new[](std::size_t count) { std::cout << "custom new[] for size " << count << '\n'; return ::operator new[](count); } }; int main() { X* p1 = new X; delete p1; X* p2 = new X[10]; delete[] p2; }
Sortie possible :
custom new for size 1 custom new[] for size 10
Les surcharges de
operator new
et
operator new[]
avec des paramètres supplémentaires définis par l'utilisateur ("formes de placement"), peuvent également être définies comme membres de classe
(
19-22
)
). Lorsque l'expression de placement
new
avec la signature correspondante recherche la fonction d'allocation à appeler, elle commence au niveau de la classe avant d'examiner la portée globale, et si le placement
new
spécifique à la classe est fourni, il est appelé.
|
Lors de l'allocation d'objets et de tableaux d'objets dont l'alignement dépasse __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la résolution de surcharge pour les formes de placement est effectuée deux fois comme pour les formes régulières : d'abord pour les signatures de fonctions sensibles à l'alignement, puis pour les signatures de fonctions non sensibles à l'alignement. |
(depuis C++17) |
|
Lors de l'allocation d'objets et de tableaux d'objets dont l'alignement ne dépasse pas __STDCPP_DEFAULT_NEW_ALIGNMENT__ , la résolution de surcharge pour les formes de placement est effectuée deux fois comme pour les formes régulières : d'abord pour les signatures de fonctions non conscientes de l'alignement, puis pour les signatures de fonctions conscientes de l'alignement. |
(depuis C++20) |
#include <cstddef> #include <iostream> #include <stdexcept> struct X { X() { throw std::runtime_error(""); } // custom placement new static void* operator new(std::size_t count, bool b) { std::cout << "custom placement new called, b = " << b << '\n'; return ::operator new(count); } // 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&) {} }
Sortie :
custom placement new called, b = 1 custom placement delete called, b = 1
Si l'opérateur
operator new
au niveau de la classe est une fonction template, il doit avoir le type de retour
void
*
, le premier argument
std::size_t
, et il doit avoir deux paramètres ou plus. En d'autres termes, seules les formes de placement peuvent être des templates.
Notes
Bien que le placement non-allouant new ( 9,10 ) ne puisse pas être remplacé, une fonction avec la même signature peut être définie au niveau de la classe comme décrit ci-dessus. De plus, les surcharges globales qui ressemblent au placement new mais prennent un type de pointeur non-void comme second argument sont autorisées, donc le code qui veut garantir que le vrai placement new est appelé (par ex. std::allocator::construct ), doit utiliser :: new et aussi convertir le pointeur en void * .
Si le comportement d'une fonction de désallocation ne satisfait pas les contraintes par défaut, le comportement est indéfini.
|
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) |
Il n'est pas spécifié si les versions de bibliothèque de
operator new
effectuent des appels à
std::malloc
ou à
std::aligned_alloc
(depuis C++17)
.
Pour charger un fichier volumineux, le mappage de fichiers via des fonctions spécifiques au système d'exploitation, par exemple,
mmap
sur POSIX ou
CreateFileMapping
(
A
/
W
) avec
MapViewOfFile
sur Windows, est préférable à l'allocation d'un tampon pour la lecture de fichiers.
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_lib_freestanding_operator_new
|
202306L
|
(C++26) | Support autonome pour operator new remplaçable [1] |
0
|
(C++26) | Aucun support autonome | |
__cpp_lib_constexpr_new
|
202406L
|
(C++26) | constexpr placement new et new [ ] |
- ↑ Formellement, cette macro se développe en 202306L si toutes les versions par défaut des fonctions d'allocation globales remplaçables satisfont aux exigences d'une implémentation hébergée.
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 521 | C++98 |
toute classe dérivée de
std::bad_alloc
pouvait être levée,
même si la base std::bad_alloc est ambiguë ou inaccessible |
l'exception levée doit correspondre
à un gestionnaire de type std::bad_alloc |
| LWG 9 | C++98 |
des appels multiples pour allouer zéro
octet pouvaient produire le même pointeur |
uniquement autorisé si tous ces pointeurs
précédemment produits ont été passés à des fonctions de désallocation |
| LWG 206 | C++98 |
le remplacement des fonctions d'allocation remplaçables
n'affectait pas les comportements par défaut des fonctions d'allocation non levantes remplaçables correspondantes |
les comportements par défaut
changent en conséquence |
| LWG 404 | C++98 |
les remplacements des fonctions d'allocation
remplaçables pouvaient être déclarés inline |
interdit, aucun diagnostic requis |
Références
- Norme C++23 (ISO/CEI 14882:2024) :
-
- 17.7 Gestion dynamique de la mémoire [support.dynamic]
- Norme C++20 (ISO/CEI 14882:2020) :
-
- 17.6 Gestion dynamique de la mémoire [support.dynamic]
- Norme C++17 (ISO/IEC 14882:2017) :
-
- 21.6 Gestion dynamique de la mémoire [support.dynamic]
- Norme C++14 (ISO/CEI 14882:2014) :
-
- 18.6 Gestion dynamique de la mémoire [support.dynamic]
- Norme C++11 (ISO/CEI 14882:2011) :
-
- 18.6 Gestion dynamique de la mémoire [support.dynamic]
- Norme C++03 (ISO/CEI 14882:2003) :
-
- 18.4 Gestion dynamique de la mémoire [lib.support.dynamic]
- Norme C++98 (ISO/CEI 14882:1998) :
-
- 18.4 Gestion dynamique de la mémoire [lib.support.dynamic]
Voir aussi
|
[static]
(C++23)
|
alloue de la mémoire en utilisant
Allocator
(fonction membre statique publique de
std::generator<Ref,V,Allocator>::promise_type
)
|
|
fonctions de désallocation
(fonction) |
|
|
(C++11)
|
obtient le gestionnaire new actuel
(fonction) |
|
enregistre un nouveau gestionnaire
(fonction) |
|
|
(obsolète en C++17)
(supprimé en C++20)
|
obtient un stockage non initialisé
(fonction template) |
|
alloue de la mémoire
(fonction) |
|
|
(C++17)
|
alloue de la mémoire alignée
(fonction) |