167 votes

Opérateurs delete et delete[] en C++

Quelle est la différence entre delete y delete[] en C++ ?

0 votes

Vous pourriez trouver cette question pertinente stackoverflow.com/questions/1913343/

7 votes

Les problèmes avec delete et delete[] sont une des raisons pour lesquelles j'aime les pointeurs intelligents, et l'utilisation de vector<> au lieu d'un tableau chaque fois que je le peux.

1 votes

199voto

Nick Meyer Points 14502

El delete L'opérateur désalloue la mémoire et appelle le destructeur d'un objet unique créé avec la commande new .

El delete [] désalloue la mémoire et appelle les destructeurs pour un tableau d'objets créés avec new [] .

Utilisation de delete sur un pointeur renvoyé par new [] o delete [] sur un pointeur renvoyé par new entraîne un comportement non défini.

3 votes

Je me demande si l'utilisation de delete sur un tableau new[] de types primitifs comme int ou char (pas de constructeur/destructeur) conduit nécessairement à un comportement non défini, aussi. Il semble que la taille du tableau ne soit pas stockée quelque part quand on utilise des types primitifs.

29 votes

Si la norme ne définit pas ce qui se passe lorsque cela est fait, il s'agit par définition d'un "comportement non défini", même si votre compilateur fait de manière déterministe ce que vous aimeriez qu'il fasse. Un autre compilateur peut faire quelque chose d'entièrement différent.

0 votes

J'ai fait cette erreur lorsque j'avais un tableau de chaînes de caractères C comme "char** strArray". Si vous avez un tableau comme moi, vous devez itérer dans le tableau et supprimer/libérer chaque élément, puis supprimer/libérer le tableau lui-même. L'utilisation de "delete[]" sur le tableau que j'ai ne fonctionne pas car (comme le soulignent les commentaires et la réponse ci-dessus), IL APPELLE LES DESTRUCTEURS, il ne libère pas réellement chaque emplacement.

94voto

El delete[] L'opérateur est utilisé pour supprimer les tableaux. Le site delete L'opérateur est utilisé pour supprimer les objets qui ne sont pas des tableaux. Il appelle operator delete[] y operator delete respectivement pour supprimer la mémoire que le tableau ou l'objet non-réseau occupait après avoir (éventuellement) appelé les destructeurs des éléments du tableau ou de l'objet non-réseau.

Le tableau suivant 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 new qui crée un tableau (donc, soit le new type[] o new appliqué à une construction de type tableau), la norme recherche un operator new[] dans la classe de type d'élément du tableau ou dans la portée globale, et passe la quantité de mémoire demandée. Il peut demander plus de N * sizeof(ElementType) s'il le souhaite (par exemple pour stocker le nombre d'éléments, afin de savoir plus tard, lors de la suppression, combien d'appels au destructeur ont été effectués). Si la classe déclare un operator new[] qui s'ajoute à la quantité de mémoire accepte un autre size_t ce second paramètre recevra le nombre d'éléments alloués - il pourra l'utiliser à toutes fins utiles (débogage, etc...).

Pour le new qui crée un objet qui n'est pas un tableau, il cherchera un objet operator new dans la classe de l'élément ou dans la portée globale. Il transmet la quantité de mémoire demandée (exactement sizeof(T) toujours).

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

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

0 votes

Si j'ai un tableau de pointeurs vers des objets, dont chacun peut être nullptr, delete[] ne supprimera pas les objets pointés par ces pointeurs, n'est-ce pas ? delete[] ne supprimera que les éléments du tableau qui sont physiquement intégrés dans le tableau. Par exemple, si vous avez un tableau de structures, le destructeur de chaque structure sera appelé. Mais pas si vous avez un tableau de pointeurs vers des structs. La mémoire des pointeurs sera libérée, mais pas la mémoire des structures qui sont pointées par ces pointeurs.

26voto

ravs2627 Points 11

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

Nous devons les utiliser de manière correspondante. Mais j'aimerais ajouter cette compréhension particulière pour la différence entre delete y delete[]

1) delete est utilisé pour désallouer la mémoire allouée à objet unique

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

class ABC{}

ABC *ptr = new ABC[100]

quand nous disons new ABC[100] Le compilateur peut obtenir l'information sur le nombre d'objets qui doivent être alloués (ici c'est 100) et appellera le constructeur pour chacun des objets créés.

mais en conséquence, si nous utilisons simplement delete ptr dans ce cas, le compilateur ne connaîtra pas le nombre d'objets que les ptr et finira par appeler le destructeur et effacer la mémoire de seulement 1 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 [] ptr dans ce cas.

4 votes

Ce devrait être la bonne réponse. Aucune des autres réponses ne mentionne la différence distincte : "mais de la même manière, si nous utilisons simplement delete ptr pour ce cas, le compilateur ne saura pas combien d'objets ce ptr pointe et finira par appeler le destructeur et effacer la mémoire pour seulement 1 objet"

1 votes

Comment faire la même chose en C ?

0 votes

@DogusUral Pourquoi ? Il n'y a pas de destructeurs en C, donc vous avez juste à free() ceci et cela. Si vous utilisez un modèle de pseudo-destructeur, vous devez l'appeler une fois pour chaque objet utilisant une balise for boucle.

6voto

san983 Points 309

Les opérateurs delete y delete [] sont utilisés respectivement pour détruire les objets créés avec new y new[] en retournant à la mémoire allouée laissée à la disposition du gestionnaire de mémoire du compilateur.

Les objets créés avec new doit nécessairement être détruit avec delete et que les tableaux créés avec new[] doit être supprimé avec delete[] .

5voto

Ekalavya Points 819

Quand j'ai posé cette question, ma vraie question était "y a-t-il une différence entre les deux ? Le runtime ne doit-il pas conserver des informations sur la taille du tableau, et ne sera-t-il donc pas capable de dire de laquelle nous parlons ?" Cette question n'apparaît pas dans les "questions connexes", donc juste pour aider ceux qui sont comme moi, voici la réponse à cette question : "pourquoi avons-nous besoin de l'opérateur delete[] ?"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X