new opérateur (C++)

Tente d’allouer et d’initialiser un objet ou un tableau d’objets d’un type d’espace réservé ou spécifié, et retourne un pointeur correctement typé et non égal à l’objet (ou à l’objet initial du tableau).

Syntaxe

new-expression:
::optnewnew-placementoptnew-type-idnew-initializeropt
::optnewnew-placementopt(type-id)new-initializeropt

new-placement:
( expression-list )

new-type-id:
type-specifier-seqnew-declaratoropt

new-declarator:
ptr-operatornew-declaratoropt
noptr-new-declarator

noptr-new-declarator:
[expression]attribute-specifier-seqopt
noptr-new-declarator[constant-expression]attribute-specifier-seqopt

new-initializer:
(expression-listopt)
braced-init-list

Notes

En cas d’échec, new retourne zéro ou lève une exception. Pour plus d’informations, consultez The new and delete Operators. Vous pouvez modifier ce comportement par défaut en écrivant une routine de gestion des exceptions personnalisée et en appelant la _set_new_handler fonction de bibliothèque d’exécution avec votre nom de fonction comme argument.

Pour plus d’informations sur la création d’un objet sur le tas managé dans C++/CLI et C++/CX, consultez gcnew.

Remarque

Les extensions de composant Microsoft C++ (C++/CX) prennent en charge les new mot clé pour ajouter des entrées d’emplacement de table virtuelle. Pour plus d’informations, consultez new (nouvel emplacement dans vtable)

Lorsqu’il new est utilisé pour allouer de la mémoire pour un objet de classe C++, le constructeur de l’objet est appelé après l’allocation de la mémoire.

Utilisez l’opérateur delete pour libérer la mémoire allouée par l’opérateur new . Utilisez l’opérateur delete[] pour supprimer un tableau alloué par l’opérateur new .

L'exemple suivant alloue, puis libère un tableau de caractères à deux dimensions de taille dim par 10. Lors de l’allocation d’un tableau multidimensionnel, toutes les dimensions à l’exception du premier doivent être des expressions constantes qui évaluent les valeurs positives. La dimension de tableau la plus à gauche peut être n’importe quelle expression qui prend la valeur positive. Lors de l’allocation d’un tableau à l’aide de l’opérateur new , la première dimension peut être égale à zéro ; l’opérateur new retourne un pointeur unique.

char (*pchar)[10] = new char[dim][10];
delete [] pchar;

Impossible type-id de contenir const, de volatiledéclarations de classe ou d’énumération. L’expression suivante est mal formée :

volatile char *vch = new volatile char[20];

L’opérateur new n’alloue pas de types de référence, car ils ne sont pas des objets.

L’opérateur new ne peut pas être utilisé pour allouer une fonction, mais il peut être utilisé pour allouer des pointeurs à des fonctions. L'exemple suivant alloue, puis libère un tableau de sept pointeurs vers des fonctions qui retournent des entiers.

int (**p) () = new (int (*[7]) ());
delete p;

Si vous utilisez l’opérateur new sans arguments supplémentaires et que vous compilez avec le /GX, /EHaou /EHs l’option, le compilateur génère du code pour appeler l’opérateur delete si le constructeur lève une exception.

La liste suivante décrit les éléments de grammaire de new:

new-placement
Fournit un moyen de transmettre des arguments supplémentaires si vous surchargez new.

type-id
Spécifie le type à allouer ; il peut s’agir d’un type intégré ou défini par l’utilisateur. Si la spécification de type est compliquée, elle peut être placée entre parenthèses pour forcer l'ordre de liaison. Le type peut être un espace réservé (auto) dont le type est déterminé par le compilateur.

new-initializer
Fournit une valeur pour l'objet initialisé. Les initialiseurs ne peuvent pas être spécifiés pour les tableaux. L’opérateur new crée des tableaux d’objets uniquement si la classe a un constructeur par défaut.

noptr-new-declarator
Spécifie les limites d’un tableau. Lors de l’allocation d’un tableau multidimensionnel, toutes les dimensions à l’exception du premier doivent être des expressions constantes qui évaluent les valeurs positives convertibles en std::size_t. La dimension de tableau la plus à gauche peut être n’importe quelle expression qui prend la valeur positive. S’applique attribute-specifier-seq au type de tableau associé.

Exemple : Allouer et libérer un tableau de caractères

L'exemple de code suivant alloue un tableau de caractères et un objet de classe CName, puis les libère.

// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>

class CName {
public:
   enum {
      sizeOfBuffer = 256
   };

   char m_szFirst[sizeOfBuffer];
   char m_szLast[sizeOfBuffer];

public:
   void SetName(char* pszFirst, char* pszLast) {
     strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
     strcpy_s(m_szLast, sizeOfBuffer, pszLast);
   }

};

int main() {
   // Allocate memory for the array
   char* pCharArray = new char[CName::sizeOfBuffer];
   strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");

   // Deallocate memory for the array
   delete [] pCharArray;
   pCharArray = NULL;

   // Allocate memory for the object
   CName* pName = new CName;
   pName->SetName("Firstname", "Lastname");

   // Deallocate memory for the object
   delete pName;
   pName = NULL;
}

Exemple : new opérateur

Si vous utilisez le formulaire de placement de l’opérateur new (le formulaire avec plus d’arguments que la taille), le compilateur ne prend pas en charge un formulaire de placement de l’opérateur delete si le constructeur lève une exception. Par exemple :

// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
   A(int) { throw "Fail!"; }
};
void F(void) {
   try {
      // heap memory pointed to by pa1 will be deallocated
      // by calling ::operator delete(void*).
      A* pa1 = new A(10);
   } catch (...) {
   }
   try {
      // This will call ::operator new(size_t, char*, int).
      // When A::A(int) does a throw, we should call
      // ::operator delete(void*, char*, int) to deallocate
      // the memory pointed to by pa2.  Since
      // ::operator delete(void*, char*, int) has not been implemented,
      // memory will be leaked when the deallocation can't occur.

      A* pa2 = new(__FILE__, __LINE__) A(20);
   } catch (...) {
   }
}

int main() {
   A a;
}

Initialisation d’objets alloués avec new

Un champ facultatif new-initializer est inclus dans la grammaire de l’opérateur new . Ce champ permet d’initialiser de nouveaux objets avec des constructeurs définis par l’utilisateur. Pour plus d’informations sur la façon dont l’initialisation est effectuée, consultez Initialiseurs. L’exemple suivant montre comment utiliser une expression d’initialisation avec l’opérateur new :

// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
    // Define default constructor and a constructor that accepts
    //  an initial balance.
    Acct() { balance = 0.0; }
    Acct( double init_balance ) { balance = init_balance; }
private:
    double balance;
};

int main()
{
    Acct *CheckingAcct = new Acct;
    Acct *SavingsAcct = new Acct ( 34.98 );
    double *HowMuch = new double { 43.0 };
    // ...
}

Dans cet exemple, l’objet CheckingAcct est alloué à l’aide de l’opérateur new , mais aucune initialisation par défaut n’est spécifiée. Par conséquent, le constructeur par défaut pour la classe, Acct()est appelé. L’objet SavingsAcct est ensuite alloué de la même façon, sauf qu’il est initialisé explicitement à 34,98. Étant donné que 34.98 est de type double, le constructeur qui accepte un argument de ce type est appelé pour gérer l’initialisation. Enfin, le type HowMuch non classe est initialisé à 43.0.

Si un objet est d’un type de classe et que cette classe a des constructeurs (comme dans l’exemple précédent), l’objet peut être initialisé par l’opérateur new uniquement si l’une de ces conditions est remplie :

  • Les arguments fournis dans l’initialiseur correspondent aux arguments d’un constructeur.

  • La classe possède un constructeur par défaut (un constructeur pouvant être appelé sans argument).

L’initialisation explicite par élément ne peut pas être effectuée lors de l’allocation de tableaux à l’aide de l’opérateur new ; seul le constructeur par défaut, le cas échéant, est appelé. Pour plus d’informations, consultez arguments par défaut.

Si l’allocation de mémoire échoue (operator new retourne une valeur de 0), aucune initialisation n’est effectuée. Ce comportement protège contre les tentatives d’initialisation des données qui n’existent pas.

Comme pour les appels de fonction, l’ordre dans lequel les expressions initialisées sont évaluées n’est pas défini. En outre, vous ne devez pas vous appuyer sur ces expressions évaluées complètement avant l’allocation de mémoire. Si l’allocation de mémoire échoue et que l’opérateur new retourne zéro, certaines expressions de l’initialiseur peuvent ne pas être évaluées complètement.

Durée de vie des objets alloués avec new

Les objets alloués avec l’opérateur new ne sont pas détruits lorsque l’étendue dans laquelle elles sont définies est terminée. Étant donné que l’opérateur new retourne un pointeur vers les objets qu’il alloue, le programme doit définir un pointeur avec une étendue appropriée pour accéder à ces objets et les supprimer. Par exemple :

// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
    // Use new operator to allocate an array of 20 characters.
    char *AnArray = new char[20];

    for( int i = 0; i < 20; ++i )
    {
        // On the first iteration of the loop, allocate
        //  another array of 20 characters.
        if( i == 0 )
        {
            char *AnotherArray = new char[20];
        }
    }

    delete [] AnotherArray; // Error: pointer out of scope.
    delete [] AnArray;      // OK: pointer still in scope.
}

Une fois que le pointeur AnotherArray sort de la portée de l'exemple, l'objet ne peut plus être supprimé.

Fonctionnement new

L’expression new-expression contenant l’opérateur new effectue trois opérations :

  • Localise et réserve le stockage pour les objets à allouer. Une fois cette étape terminée, la quantité correcte de stockage est allouée, mais elle n’est pas encore un objet.

  • Initialise les objets. Une fois que l'initialisation est terminée, les informations disponibles sont suffisantes pour que le stockage alloué soit un objet.

  • Retourne un pointeur vers le ou les objets d’un type de pointeur dérivé ou new-type-idtype-id. Le programme utilise ce pointeur pour accéder au nouvel objet alloué.

L’opérateur new appelle la fonction operator new. Pour les tableaux de n’importe quel type et pour les objets qui ne sont pas class, structou union les types, une fonction globale, ::operator newsont appelés pour allouer le stockage. Les objets de type classe peuvent définir leur propre operator new fonction membre statique par classe.

Lorsque le compilateur rencontre l’opérateur new pour allouer un objet de type T, il émet un appel T::operator new( sizeof(T) ) ou, si aucun utilisateur n’est défini operator new , ::operator new( sizeof(T) ). Il s’agit de la façon dont l’opérateur new peut allouer la quantité de mémoire correcte pour l’objet.

Remarque

Argument auquel operator new est de type std::size_t. Ce type est défini dans <direct.h>, <malloc.h>, <memory.h>, <search.h, <stddef.h>>, <stdio.h>, <stdlib.h>, <string.h et time.h>>.<

Une option de la grammaire autorise la spécification de new-placement (voir la grammaire pour new l’opérateur). Le new-placement paramètre ne peut être utilisé que pour les implémentations définies par l’utilisateur ; operator newil permet de transmettre des informations supplémentaires à operator new. Expression avec un new-placement champ tel qu’il T *TObject = new ( 0x0040 ) T; est traduit en T *TObject = T::operator new( sizeof( T ), 0x0040 ); si la classe T a un membre operator new, sinon en T *TObject = ::operator new( sizeof( T ), 0x0040 );.

L’intention initiale du new-placement champ était d’autoriser l’allocation d’objets dépendants du matériel aux adresses spécifiées par l’utilisateur.

Remarque

Bien que l’exemple précédent n’affiche qu’un seul argument dans le new-placement champ, il n’existe aucune restriction sur le nombre d’arguments supplémentaires pouvant être passés de operator new cette façon.

Même si elle operator new a été définie pour un type de Tclasse, vous pouvez utiliser explicitement l’opérateur new global, comme dans cet exemple :

T *TObject = ::new TObject;

L’opérateur de résolution d’étendue (::) force l’utilisation de l’opérateur global new .

Voir aussi

Expressions avec des opérateurs unaires
Mots clés
new et delete opérateurs