2010-02-24 3 views
4

comment fonctionne l'opérateur de suppression? Est-ce mieux alors gratuit()? Aussi, si vous faites ptr=new char[10], puis supprimez en utilisant delete ptr, comment le pointeur sait combien d'emplacements à supprimer.Comment la suppression en C++ sait combien d'emplacements de mémoire à supprimer

+4

Je pense que vous voulez dire l'opérateur 'delete'. – SLaks

+12

vous devez faire supprimer [] ptr sinon vous avez des ennuis. –

+0

J'ai pris la liberté de clarifier votre titre, j'espère que cela ne vous dérange pas. Aussi, si vous vous posez des questions sur un compilateur et une plateforme spécifiques, il serait peut-être bon de l'inclure. Différents compilateurs peuvent avoir différentes façons de s'attaquer au problème que vous posez. – Skurmedel

Répondre

15

Il n'y a que l'opérateur delete, free Existe seulement en tant que fonction. Sous C++, vous êtes encouragé à utiliser new/delete sur malloc()/free().


Il existe une "magie" interne dans l'opérateur de suppression. Lorsqu'un tableau est créé avec new[], la taille du tableau est stockée dans les métadonnées du bloc de mémoire. delete[] utilise cette information.

Tout ceci dépend bien sûr du compilateur, de l'OS, de l'optimiseur et de l'implémentation.

+0

Je suggère de remplacer 'new' par' new [] 'et' delete' par 'delete []'. – fredoverflow

+4

Si vous utilisez par erreur 'delete ptr' au lieu de' delete [] ptr', la "magie" peut ou ne peut pas fonctionner correctement, encore une fois très dépendante de l'implémentation. –

+0

@FredOverflow, @Mark: en effet, merci! – Vlad

1

Ajouter à @ la réponse de Vlad si vous allouez de la mémoire en utilisant les nouvelles [] sous forme de l'opérateur comme:

char *c = new char[10]; 

alors vous devez utiliser le formulaire de suppression correspondant:

delete[] c; 

Vous devez Dites explicitement au compilateur d'utiliser les métadonnées lors du désallocation.

[EDIT]

Pourquoi vous ne pouvez pas utiliser char c []

Parce que le compilateur a besoin de connaître la taille, il a besoin de mettre de côté pour la variable c au moment de la compilation. Toutefois, l'utilisation du nouveau formulaire [] lui permet de reporter l'allocation jusqu'à l'exécution. Par conséquent, l'erreur du compilateur.

+0

'char c [] = new char [10];' ne compile pas, vous devriez changer 'c []' en '* c'. – fredoverflow

+0

cette instruction n'est pas légale, vous ne pouvez pas changer le pointeur d'un tableau de caractères. Je pense que vous vouliez dire char * c – shreyasva

+0

Merci d'avoir signalé l'erreur. Fait la correction. – ardsrk

2
  1. En C++, un constructeur est appelé en utilisant new, mais pas en utilisant malloc. De même, un destructeur est appelé lors de l'utilisation de delete, mais pas lors de l'utilisation de free. Si vous avez créé un tableau en utilisant MyClass * x = new MyClass [25], vous devez appeler delete [] x pour que le système sache qu'il supprime (et détruit) un groupe d'objets au lieu d'un seul.

2

L'implémentation calcule le nombre d'éléments à détruire (lors de l'utilisation de delete []) pour vous. Par exemple:

  • new char [10] pourrait allouer quelques octets supplémentaires, mettre le nombre d'éléments au début, puis retourner le pointeur au premier élément après cela. delete [] pourrait alors regarder derrière le pointeur au nombre stocké
  • stocker l'équivalent de std :: map < void *, size_t >, et nouveau T [n] créerait une clé avec le pointeur retourné, et une valeur avec le décompte. supprimer [] rechercherait le pointeur sur cette carte
  • quelque chose de complètement différent. Ce n'est pas grave pour vous comment c'est fait, juste que c'est fait (et comme d'autres réponses l'ont souligné, utilisez delete [] avec new [] !!)
4

si vous faites un type non-tableau:

T t = new T; 
// ... 
delete t; 

Il saura beaucoup à supprimer parce qu'il sait grand T est. Si vous faites un tableau:

T t* = new T[10]; 
// ... 
delete [] t; 

Il définira quelques informations supplémentaires avec l'allocation pour lui dire combien supprimer. Notez, nous utilisons delete [] t avec le [] supplémentaire pour dire que c'est un tableau. Si vous ne faites pas cela, il va penser que c'est juste un T et seulement libérer beaucoup de mémoire.

Toujours utiliser delete si vous utilisez new et free si vous utilisez malloc. new fait 2 choses d'abord il alloue la mémoire, puis il construit l'objet. De même delete appelle le destructeur, puis libère la mémoire. malloc\free seulement traitent l'allocation de mémoire et la désallocation.

2

Ce n'est pas une question de mieux ou de pire. Les deux sont des opérations ayant le même but, l'allocation et la libération de la mémoire, mais généralement utilisées dans un contexte différent de C vs. C++. En outre, il existe des différences importantes entre les deux ensembles d'opérations:

  • new/delete sont les mots-clés C, et ne sont pas disponibles dans la langue C
  • new/delete sont de type sécurité, alors que malloc()/free() sont ne pas. Cela signifie que les pointeurs renvoyés par malloc() et free() sont des pointeurs void qui doivent être castés au bon type.
  • new/delete soutenir implicitement l'allocation et la suppression tableau en utilisant la syntaxe new[] et delete[] en utilisant des méta-données fournies par le compilateur, malloc()/free() ne prennent pas en charge cette syntaxe
  • application new/delete à un type de classe T appellera la constructeur et destructor respectivement de T, malloc()/free() ne pas appeler le constructeur et destructor de T
  • malloc() retournera NULL en cas d'épuisement de la mémoire, new lancera une exception

Notez que pour éviter la corruption de la mémoire, la mémoire allouée à l'aide new doit être libéré en utilisant delete. La même chose vaut pour la mémoire allouée en utilisant malloc(), qui devrait être libérée en utilisant free().

2

Répondant spécifiquement à votre question, l'opérateur de suppression invoque le destructeur, ce qui n'est pas le cas pour le destructeur; d'où la raison pour laquelle vous ne voulez pas mélanger malloc/free avec new/delete. Lorsque la bibliothèque du compilateur récupère la mémoire du tas, elle en saisit un peu plus que ce que vous lui demandez, ce qui inclut de l'espace pour sa gestion interne, certaines métadonnées et, si nécessaire, un remplissage.

Dites-vous 128 octets malloc, ou un nouveau tableau de huit objets de 16 octets.Le compilateur peut en effet saisir 256 octets, inclure un petit bloc de gestion de tas au début, enregistrer qu'il vous a donné 128 mais saisi 256, et vous renvoyer un décalage dans ce bloc 256 quelque part après son en-tête. Vous avez la garantie qu'à partir de ce pointeur, vous avez 128 octets que vous pouvez utiliser, mais si vous allez au-delà, vous pourriez avoir des problèmes. Les opérateurs gratuits et supprimés sous le capot prendront le pointeur que vous avez reçu, sauvegarderont un décalage connu, liront le bloc d'en-tête et sauront relâcher 256 octets dans le tas.

Questions connexes