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
:
::
optnew
new-placement
optnew-type-id
new-initializer
opt
::
optnew
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 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 volatile
dé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
, /EHa
ou /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-id
type-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
, struct
ou union
les types, une fonction globale, ::operator new
sont 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 new
il 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 T
classe, 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
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour