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 à l’objet (ou à l’objet initial du tableau) correctement typé et non égal à zéro.
Syntaxe
new-expression
:
::
opt new
new-placement
opt new-type-id
new-initializer
opt
::
opt new
new-placement
opt (
type-id
)
new-initializer
opt
new-placement
:
(
expression-list
)
new-type-id
:
type-specifier-seq
new-declarator
opt
new-declarator
:
ptr-operator
new-declarator
opt
noptr-new-declarator
noptr-new-declarator
:
[
expression
]
attribute-specifier-seq
opt
noptr-new-declarator
[
constant-expression
]
attribute-specifier-seq
opt
new-initializer
:
(
expression-list
opt )
braced-init-list
Notes
En cas d’échec, new
retourne zéro ou lève une exception. Pour plus d’informations, consultez Opérateurs new
et delete
. Vous pouvez modifier ce comportement par défaut en écrivant une routine personnalisée de gestion des exceptions et en appelant la fonction de bibliothèque du runtime _set_new_handler
avec le nom de fonction comme argument.
Pour plus d’informations sur la façon de créer un objet sur le tas managé en C++/CLI et C++/CX, consultez gcnew.
Remarque
Microsoft C++ Component Extensions (C++/CX) fournit la prise en charge du mot clé new
pour ajouter des entrées d’emplacement vtable. Pour plus d’informations, consultez new
(nouvel emplacement dans vtable)
Lorsque new
est utilisé pour allouer la mémoire à un objet de classe C++, le constructeur de l’objet est appelé après que la mémoire est allouée.
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 sauf la première doivent être des expressions constantes évaluées comme valeurs positives. La dimension du tableau la plus à gauche peut être toute expression évaluée comme valeur positive Lors de l’allocation d’un tableau à l’aide de l’opérateur new
, la première dimension peut être zéro. L’opérateur new
retourne un seul pointeur.
char (*pchar)[10] = new char[dim][10];
delete [] pchar;
type-id
ne peut pas contenir const
, volatile
, des déclarations de classe ou des déclarations 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 référence, car il ne s’agit pas d’objets.
L’opérateur new
ne peut pas être utilisé pour allouer une fonction. En revanche, il peut être utilisé pour allouer des pointeurs vers 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 argument supplémentaire, et que vous compilez avec l’option /GX
, /EHa
, ou /EHs
, 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
Permet 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’un type 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 des 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 sauf la première doivent être des expressions constantes évaluées comme valeurs positives convertibles en std::size_t
. La dimension du tableau la plus à gauche peut être toute expression évaluée comme valeur positive attribute-specifier-seq
s’applique 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 : Opérateur new
Si vous utilisez la forme de placement de l’opérateur new
(la forme avec davantage d’arguments que la taille), le compilateur ne prend pas en charge une forme 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 des objets alloués avec new
Un champ new-initializer
facultatif est inclus dans la grammaire pour l’opérateur new
. Ce champ permet aux nouveaux objets d’être initialisés 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é. Ensuite, l’objet SavingsAcct
est alloué de la même façon, mais il est initialisé explicitement à 34,98. Comme 34,98 est du type double
, le constructeur qui prend un argument de ce type est appelé pour traiter l’initialisation. Pour finir, le type sans classe HowMuch
est initialisé à 43,0.
Si un objet est d’un type 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 des conditions suivantes est remplie :
Les arguments fournis dans l’initialiseur correspondent à ceux 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 en allouant des tableaux à l’aide de l’opérateur new
; seul le constructeur par défaut, s’il est présent, est appelé. Pour plus d’informations, consultez Arguments par défaut.
Si l’allocation de mémoire échoue (operator new
retourne la valeur 0), aucune initialisation n’est effectuée. Ce comportement empêche les tentatives d’initialisation de données qui n’existent pas.
Comme avec 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 attendre à ce que ces expressions soient complètement évaluées avant que l’allocation de mémoire ait eu lieu. Si l’allocation de mémoire échoue et que l’opérateur new
retourne zéro, certaines expressions dans l’initialiseur risquent de ne pas être entièrement évaluées.
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 vous quittez l’étendue dans laquelle ils sont définis. Comme l’opérateur new
retourne un pointeur désignant 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é.
Comment new
fonctionne
new-expression
(l’expression contenant l’opérateur new
) effectue trois opérations :
Localise et réserve le stockage pour les objets à allouer. Lorsque cette phase est terminée, la quantité correcte d’espace de stockage est allouée, mais ce 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 les objets d’un type pointeur dérivé de
new-type-id
ou detype-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 tout type et pour les objets qui ne sont pas de type class
, struct
ou union
, une fonction globale, ::operator new
, est appelée pour allouer le stockage. Les objets de type de classe peuvent définir leur propre fonction membre statique operator new
pour chaque 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 operator new
défini par l’utilisateur n’est défini, ::operator new( sizeof(T) )
. C’est ainsi que l’opérateur new
peut allouer la quantité correcte de mémoire pour l’objet.
Remarque
L’argument de 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 dans la grammaire permet la spécification de new-placement
(consultez la grammaire correspondant à l’opérateur new
). Le paramètre new-placement
peut être utilisé uniquement pour les implémentations définies par l’utilisateur de operator new
; il permet de transmettre des informations supplémentaires à operator new
. Une expression avec un champ new-placement
tel que T *TObject = new ( 0x0040 ) T;
est traduite en T *TObject = T::operator new( sizeof( T ), 0x0040 );
si la classe T comporte un opérateur membre operator new
; autrement, elle est traduite en T *TObject = ::operator new( sizeof( T ), 0x0040 );
.
L’objectif initial du champ new-placement
est de permettre l’allocation d’objets dépendants du matériel à des adresses spécifiées par l’utilisateur.
Remarque
Bien que l’exemple précédent indique un seul argument dans le champ new-placement
, il n’existe aucune restriction quant au nombre d’arguments supplémentaires pouvant être transmis à operator new
de cette façon.
Même lorsque operator new
a été défini pour un type classe T
, 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 new
global.
Voir aussi
Expressions avec des opérateurs unaires
Mots clés
Opérateurs new
et delete