opérateurs delete vs delete [] en C ++

136

Quelle est la différence entre les opérateurs deleteet delete[]en C ++?

Shreyasva
la source
Vous pourriez trouver cette question pertinente stackoverflow.com/questions/1913343/…
Sharptooth
7
Les problèmes avec delete et delete [] sont une des raisons pour lesquelles j'aime les pointeurs intelligents et utiliser à la vector<>place d'un tableau chaque fois que je le peux.
David Thornley
@DavidThornley Si vous utilisez des pointeurs intelligents, vous devez toujours connaître la différence dans le sens où vous devez toujours savoir ne pas écrire, par exemple std::unique_ptr<int>(new int[3]), car il appellera regular deletesur le tableau qui est un comportement non défini. Au lieu de cela, vous devez utiliserstd::unique_ptr<int[]>
Arthur Tacca

Réponses:

151

L' deleteopérateur libère la mémoire et appelle le destructeur pour un seul objet créé avec new.

L' delete []opérateur libère la mémoire et appelle des destructeurs pour un tableau d'objets créés avec new [].

L'utilisation deletesur un pointeur renvoyé par new []ou delete []sur un pointeur renvoyé par newentraîne un comportement non défini.

Nick Meyer
la source
3
Je me demande si l'utilisation de delete sur un nouveau [] tableau de types primitifs comme int ou char (pas de constructeur / destructeur) conduit aussi nécessairement à un comportement indéfini. Il semble que la taille du tableau n'est stockée nulle part lors de l'utilisation de types primitifs.
thomiel
21
Si la norme ne définit pas ce qui se passe lorsque cela est fait, c'est par définition un "comportement indéfini", même si votre compilateur fait de manière déterministe ce que vous voudriez qu'il fasse. Un autre compilateur peut faire quelque chose de complètement différent.
Rob K
J'ai fait cette erreur quand j'avais un tableau de chaînes C comme "char ** strArray". Si vous avez un tableau comme moi, vous devez parcourir le tableau et supprimer / libérer chaque élément, puis supprimer / libérer le strArray lui-même. Utiliser "delete []" sur le tableau que j'ai ne fonctionne pas depuis (comme indiqué par les commentaires et la réponse ci-dessus), IL APPELLE DESTRUCTEURS, il ne libère pas réellement chaque emplacement.
Katianie
88

L' delete[]opérateur est utilisé pour supprimer des tableaux. L' deleteopérateur est utilisé pour supprimer des objets non-tableau. Il appelle operator delete[]et operator deletefonctionne respectivement pour supprimer la mémoire occupée par le tableau ou l'objet non-tableau après avoir (éventuellement) appelé les destructeurs pour les éléments du tableau ou l'objet non-tableau.

Ce qui suit montre les relations:

typedef int array_type[1];

// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;

// create and destroy an int
int *b = new int;
delete b;

// create and destroy an int[1]
int *c = new int[1];
delete[] c;

// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;

Pour le newqui crée un tableau (donc, soit le new type[]soit newappliqué à une construction de type tableau), le Standard recherche un operator new[]dans la classe de type d'élément du tableau ou dans la portée globale et transmet la quantité de mémoire demandée. Il peut demander plus que N * sizeof(ElementType)s'il le souhaite (par exemple pour stocker le nombre d'éléments, de sorte que plus tard, lors de la suppression, il sait combien d'appels de destructeur à done). Si la classe déclare un operator new[]qui supplémentaire à la quantité de mémoire en accepte un autresize_t , ce deuxième paramètre recevra le nombre d'éléments alloués - elle peut l'utiliser pour n'importe quel but (débogage, etc ...).

Pour le newqui crée un objet non-tableau, il recherchera un operator newdans la classe de l'élément ou dans la portée globale. Il passe la quantité de mémoire demandée (exactement sizeof(T)toujours).

Pour le delete[], il examine le type de classe d'élément des tableaux et appelle leurs destructeurs. La operator delete[]fonction utilisée est celle de la classe du type d'élément, ou s'il n'y en a pas alors dans la portée globale.

Pour le delete, si le pointeur passé est une classe de base du type de l'objet réel, la classe de base doit avoir un destructeur virtuel (sinon, le comportement n'est pas défini). S'il ne s'agit pas d'une classe de base, alors le destructeur de cette classe est appelé et un operator deletedans cette classe ou le global operator deleteest utilisé. Si une classe de base a été transmise, le destructeur du type d'objet réel est appelé et l' operator deleteélément trouvé dans cette classe est utilisé, ou s'il n'y en a pas, un global operator deleteest appelé. Si le operator deletedans la classe a un deuxième paramètre de type size_t, il recevra le nombre d'éléments à désallouer.

Johannes Schaub - litb
la source
18

C'est l'utilisation de base du modèle allocate / DE-allocate en c ++ malloc/ free, new/ delete, new[]/delete[]

Nous devons les utiliser en conséquence. Mais je voudrais ajouter cette compréhension particulière de la différence entre deleteetdelete[]

1) deleteest utilisé pour désallouer la mémoire allouée à un seul objet

2) delete[]est utilisé pour désallouer la mémoire allouée au tableau d'objets

class ABC{}

ABC *ptr = new ABC[100]

quand nous disons new ABC[100], le compilateur peut obtenir les informations sur le nombre d'objets à allouer (ici c'est 100) et appellera le constructeur pour chacun des objets créés

mais en conséquence si nous utilisons simplement delete ptrpour ce cas, le compilateur ne saura pas combien d'objets ptrpointent et finira par appeler le destructeur et supprimer la mémoire pour un seul objet (laissant l'invocation des destructeurs et la désallocation des 99 objets restants). Il y aura donc une fuite de mémoire.

nous devons donc utiliser delete [] ptrdans ce cas.

ravs2627
la source
3
Cela devrait être la bonne réponse. Aucune des autres réponses ne mentionne la différence distincte: "mais en conséquence, si nous utilisons simplement delete ptr pour ce cas, le compilateur ne saura pas combien d'objets pointé ptr et finira par appeler le destructeur et supprimer la mémoire pour un seul objet"
Don Larynx
1
Comment réaliser la même chose en C?
Dogus Ural
@DogusUral Pourquoi? Il n'y a pas de destructeurs en C, donc vous n'avez que free()ceci et cela. Si vous utilisez un modèle de pseudo-destructeur, vous devez l'appeler une fois pour chaque objet utilisant une forboucle.
Kotauskas
@DonLarynx la différence correcte est que les mélanger aboutit à un programme mal formé. Une implémentation peut savoir combien d'objets à détruire, ou non . Il est permis de savoir qu'il a été mal appelé et d'interrompre le programme en vous indiquant où se trouve le problème.
Caleth
6

Les opérateurs deleteet delete []servent respectivement à détruire les objets créés avec newet new[], en retournant à la mémoire allouée laissée disponible au gestionnaire de mémoire du compilateur.

Les objets créés avec newdoivent nécessairement être détruits avec deleteet que les tableaux créés avec new[]doivent être supprimés avec delete[].

san983
la source
2

Lorsque j'ai posé cette question, ma vraie question était: "Y a-t-il une différence entre les deux? Le moteur d'exécution ne doit-il pas conserver des informations sur la taille du tableau, et ne pourra-t-il donc pas dire de quoi nous parlons?" Cette question n'apparaît pas dans les "questions connexes", donc juste pour aider ceux comme moi, voici la réponse à cela: "pourquoi avons-nous même besoin de l'opérateur delete []?"

Ekalavya
la source
Merci d'être revenu et d'avoir mis ça.
Ziffusion
0

deleteest utilisé pour un seul pointeur et delete[]est utilisé pour supprimer un tableau via un pointeur. Cela pourrait vous aider à mieux comprendre.

nishant arora
la source
-6

Eh bien .. peut-être que je pense que c'est juste pour explicite. L'opérateur deleteet l'opérateur delete[]sont distingués mais l' deleteopérateur peut également libérer le tableau.

test* a = new test[100];
delete a;

Et déjà vérifié ce code n'a pas de fuite de mémoire.

Bonjour le monde
la source