Namespaces
Variants

operator new , operator new[]

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)
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.

1-8) Fonctions d'allocation remplaçables . La bibliothèque standard fournit des implémentations par défaut pour ces fonctions, pour les effets des implémentations par défaut, voir ci-dessous .
9,10) Appelé par les expressions placement new standard . N'effectue aucune action et retourne ptr inchangé.
Si cette fonction est appelée via le placement new et que ptr est un pointeur nul, le comportement est indéfini.
11-22) Fonctions d'allocation définies par l'utilisateur appelées par les expressions new .

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

1-4) Si l'allocation réussit, un pointeur non nul p0 qui pointe vers une mémoire correctement alignée d'une taille d'au moins size et qui est différent de toute valeur précédemment retournée p1 , sauf si cette valeur p1 a été ultérieurement passée à une fonction de désallocation remplaçable ; si l'allocation échoue, ne retourne pas (une exception est levée, voir ci-dessous).
5-8) Identique à ( 1-4 ) , mais renvoie un pointeur nul si l'allocation échoue.
9,10) ptr
11-22) Identique à ( 1-4 ) si la fonction ne retourne pas en cas d'échec d'allocation, sinon identique à ( 5-8 ) .

Exceptions

1-4) Lance une exception d'un type qui correspondrait à un gestionnaire de type std::bad_alloc en cas d'échec d'allocation de mémoire.
11-22) Identique à ( 1-4 ) si la fonction ne retourne pas en cas d'échec d'allocation, sinon identique à ( 5-8 ) .

Remplacements globaux

Surcharges ( 1-8 ) sont remplaçables . Les effets des versions par défaut sont :

1) Tente d'allouer le stockage demandé. Le fait que cette tentative implique un appel à std::malloc ou à std::aligned_alloc n'est pas spécifié.
  • 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.
2) Retourne operator new ( count ) .
3) Identique à (1) .
4) Retourne operator new ( count, al ) .
5-8) Appelle (1-4) respectivement avec les mêmes arguments à l'exception de tag .
  • 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 [ ]
  1. 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)
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)
alloue de la mémoire alignée
(fonction)