Contexte: J'essaie de comprendre les pointeurs, nous les avons vus il y a quelques semaines à l'école et en pratiquant aujourd'hui, je suis tombé sur un idiot? problème, cela peut être très simple pour vous, mais j'ai peu ou pas d'expérience en programmation.
J'ai vu pas mal de questions dans SO sur la suppression de pointeurs, mais elles semblent toutes liées à la suppression d'une classe et non d'un pointeur `` simple '' (ou quel que soit le terme approprié), voici le code que j'essaie de courir:
#include <iostream>;
using namespace std;
int main() {
int myVar,
*myPointer;
myVar = 8;
myPointer = &myVar;
cout << "delete-ing pointers " << endl;
cout << "Memory address: " << myPointer << endl;
// Seems I can't *just* delete it, as it triggers an error
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
// pointer being freed was not allocated
// *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6
// Using the new keyword befor deleting it works, but
// does it really frees up the space?
myPointer = new int;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer continues to store a memory address.
// Using NULL before deleting it, seems to work.
myPointer = NULL;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer returns 0.
}
Donc mes questions sont:
- Pourquoi le premier cas ne fonctionnera-t-il pas? Semble l'utilisation la plus simple pour utiliser et supprimer un pointeur? L'erreur indique que la mémoire n'a pas été allouée mais «cout» a renvoyé une adresse.
- Sur le deuxième exemple, l'erreur n'est pas déclenchée mais faire un cout de la valeur de myPointer renvoie toujours une adresse mémoire?
- Le n ° 3 fonctionne-t-il vraiment? Cela me semble fonctionner, le pointeur ne stocke plus d'adresse, est-ce la bonne façon de supprimer un pointeur?
Désolé pour la longue question, je voulais que cela soit aussi clair que possible, aussi pour le répéter, j'ai peu d'expérience en programmation, donc si quelqu'un pouvait répondre à cette question en utilisant des termes simples, ce serait grandement apprécié!
la source
delete
ce que vousnew
. Il n'est pas non plus nécessaire que le pointeur se définisse sur NULL après l'avoir supprimé. Si vous voulez la sécurité là-bas, utilisez des pointeurs intelligents, qui libèrent la mémoire pour vous et donnent des erreurs lorsque vous essayez d'y accéder alors qu'ils ne contiennent pas quelque chose.reset
et cela libère l'ancien. Pour le libérer sans remplacement, vous appelezrelease
. Lorsqu'il est hors de portée, il est détruit et peut libérer la mémoire en fonction de son type.std::unique_ptr
est destiné à un seul propriétaire.std::shared_ptr
le libère lorsque le dernier propriétaire cesse de posséder la ressource. Ils sont également exceptionnellement sûrs. Si vous allouez une ressource avec une, puis rencontrez une exception, la ressource sera correctement libérée.Réponses:
1 et 2
La première variable a été allouée sur la pile. Vous ne pouvez appeler delete que sur la mémoire que vous avez allouée dynamiquement (sur le tas) à l'aide de l'
new
opérateur.3.
Ce qui précède n'a rien fait du tout . Vous n'avez rien libéré, comme le pointeur pointait sur NULL.
Ce qui suit ne doit pas être fait:
Vous l'avez pointé sur NULL, laissant derrière vous une fuite de mémoire (le nouvel int que vous avez alloué). Vous devez libérer la mémoire que vous pointez. Il n'y a plus moyen d'accéder à ce qui est alloué
new int
, d'où une fuite de mémoire.La bonne manière:
La meilleure façon:
Si vous utilisez C ++, n'utilisez pas de pointeurs bruts. Utilisez plutôt des pointeurs intelligents qui peuvent gérer ces choses pour vous avec peu de frais généraux. C ++ 11 est livré avec plusieurs fichiers .
la source
delete myPointer
désalloue*myPointer
. C'est correct. MaismyPointer
continue de pointer vers un emplacement mémoire qui a été libéré et ne doit pas être utilisé car il s'agit d'UB. Il ne sera inaccessible après la fin de la portée que SI c'était une variable locale en premier lieu.new
tous les jours. (I'm cheesy!)NULL
nous empêche de l'utiliser à mauvais escient plus tard.Je pense que vous ne comprenez pas parfaitement le fonctionnement des pointeurs.
Lorsque vous avez un pointeur pointant vers une mémoire, il y a trois choses différentes que vous devez comprendre:
- il y a "ce qui est pointé" par le pointeur (la mémoire)
- cette adresse mémoire
- tous les pointeurs n'ont pas besoin d'avoir leur mémoire supprimée: vous seulement besoin de supprimer la mémoire allouée dynamiquement (
new
opérateur utilisé ).Imaginer:
Quand tu as fait
C ++ vous permet d'essayer
delete
un pointeur qui pointenull
mais il ne fait rien, ne donne simplement aucune erreur.la source
Les pointeurs sont similaires aux variables normales en ce sens que vous n'avez pas besoin de les supprimer. Ils sont supprimés de la mémoire à la fin de l'exécution d'une fonction et / ou à la fin du programme.
Vous pouvez cependant utiliser des pointeurs pour allouer un 'bloc' de mémoire, par exemple comme ceci:
Cela allouera de l'espace mémoire pour 20000 entiers. Utile, car la pile a une taille limitée et vous voudrez peut-être vous amuser avec une grosse charge d '«ints» sans erreur de débordement de pile.
Chaque fois que vous appelez new, vous devez alors «supprimer» à la fin de votre programme, car sinon vous obtiendrez une fuite de mémoire, et une partie de l'espace mémoire alloué ne sera jamais retournée à d'autres programmes. Pour faire ça:
J'espère que cela pourra aider.
la source
nouveau n'est jamais appelé. Ainsi, l'adresse que cout imprime est l'adresse de l'emplacement mémoire de myVar, ou la valeur affectée à myPointer dans ce cas. En écrivant:
vous dites:
Il renvoie une adresse qui pointe vers un emplacement mémoire qui a été supprimé. Parce que vous créez d'abord le pointeur et attribuez sa valeur à myPointer, ensuite vous le supprimez, troisièmement vous l'imprimez. Donc, sauf si vous attribuez une autre valeur à myPointer, l'adresse supprimée restera.
NULL est égal à 0, vous supprimez 0, donc vous ne supprimez rien. Et c'est logique qu'il affiche 0 parce que vous l'avez fait:
ce qui équivaut à:
la source
la source
la source