Je me suis toujours demandé pourquoi le réglage automatique du pointeur sur NULL après supprimer ne faisait pas partie de la norme. Si cela est résolu, la plupart des plantages dus à un pointeur non valide ne se produiraient pas. Mais après avoir dit que je peux penser à quelques raisons pour lesquelles la norme aurait limité cela:
Performance:
Une instruction supplémentaire pourrait ralentir les performances de
delete
.Serait-ce à cause des pointeurs
const
.Là encore, la norme aurait pu faire quelque chose pour ce cas spécial, je suppose.
Est-ce que quelqu'un connaît les raisons exactes de ne pas autoriser cela?
Stroustrup lui-même répond. Un extrait:
C++ autorise explicitement une implémentation de delete pour mettre à zéro un opérande lvalue, et j'avais espéré que les implémentations feraient cela, mais cette idée ne semble pas être devenue populaire auprès des implémenteurs.
Mais le principal problème qu'il soulève est que l'argument de suppression n'a pas besoin d'être une valeur l.
Tout d'abord, la définition de null nécessiterait une variable stockée en mémoire. Il est vrai que vous avez généralement un pointeur dans une variable mais parfois vous voudrez peut-être supprimer un objet à une adresse juste calculée. Ce serait impossible avec la suppression de "l'annulation".
Vient ensuite la performance. Vous avez peut-être écrit du code de telle manière que le pointeur se trouve hors de portée immédiatement après la fin de delete. Le remplir avec null n'est qu'une perte de temps. Et C++ est un langage avec l'idéologie "n'en avez pas besoin? Alors vous n'avez pas à payer pour cela".
Si vous avez besoin de sécurité, il existe une large gamme de pointeurs intelligents à votre service ou vous pouvez écrire le vôtre - meilleur et plus intelligent.
Vous pouvez avoir plusieurs pointeurs pointant vers cette mémoire. Cela créerait un faux sentiment de sécurité si le pointeur que vous avez spécifié pour la suppression était défini sur null, mais pas tous les autres pointeurs. Un pointeur n'est rien d'autre qu'une adresse, un nombre. Il pourrait tout aussi bien s'agir d'un int avec une opération de déréférencement. Mon point est que vous devez également analyser chaque pointeur pour trouver ceux qui font référence à la même mémoire que vous venez de supprimer, et les annuler également. Il serait intensif en termes de calcul de scanner tous les pointeurs pour cette adresse et de les annuler, car le langage n'est pas conçu pour cela. (Bien que d'autres langues structurent leurs références pour atteindre un objectif similaire d'une manière différente.)
Un pointeur peut être enregistré dans plusieurs variables, la définition de l'une d'entre elles sur NULL laisserait toujours des pointeurs invalides dans les autres variables. Donc, vous ne gagnez pas vraiment beaucoup, vous êtes plus susceptible de créer un faux sentiment de sécurité.
En plus de cela, vous pouvez créer votre propre fonction qui fait ce que vous voulez:
template<typename T>
void deleten(T *&ptr) {
delete ptr;
ptr = NULL;
}
Parce qu'il n'y en a pas vraiment besoin, et parce qu'il faudrait supprimer en prenant pointeur vers pointeur plutôt que juste pointeur.
delete
est principalement utilisé dans les destructeurs, auquel cas la définition d'un membre sur NULL est inutile. Quelques lignes plus tard, à la clôture }
, le membre n'existe plus. Dans les opérateurs d'affectation, une suppression est généralement suivie d'une affectation de toute façon.
En outre, cela rendrait le code suivant illégal:
T* const foo = new T;
delete foo;
Voici une autre raison; Supposons que la suppression définisse son argument sur NULL:
int *foo = new int;
int *bar = foo;
delete foo;
La barre doit-elle être définie sur NULL? Pouvez-vous généraliser cela?
Si vous disposez d'un tableau de pointeurs et que votre deuxième action consiste à supprimer le tableau vide, il n'y a aucun point définissant chaque valeur sur null lorsque la mémoire est sur le point d'être libérée. Si vous voulez que ce soit nul .. écrivez null dessus :)
C++ vous permet de définir votre propre opérateur new et delete afin que, par exemple, ils utilisent votre propre allocateur de pool. Si vous faites cela, il est possible d'utiliser new et delete avec des éléments qui ne sont pas strictement des adresses mais des index dans votre tableau de pool. Dans ce contexte, la valeur de NULL (0) peut avoir une signification légale (se référant au premier élément du pool).
. La valeur non valide peut ne pas toujours être NULL.
La philosophie du C++ est "ne le payez que si vous l'utilisez". Je pense que cela peut répondre à votre question.
Parfois, vous pouvez également avoir votre propre tas qui récupérera la mémoire supprimée .. ou parfois un pointeur n'appartenant à aucune variable. Ou un pointeur stocké dans quelques variables - il est possible de mettre à zéro une seule d'entre elles.
Comme vous pouvez le voir, il y a de nombreux problèmes et problèmes possibles.
La définition automatique du pointeur sur NULL ne résoudrait pas la plupart des problèmes liés à une mauvaise utilisation du pointeur. Le seul plantage qu'il éviterait serait de le supprimer deux fois. Et si vous appelez une fonction membre sur un tel pointeur? Il se bloquerait toujours (en supposant qu'il accède aux variables membres). C++ ne vous empêche pas d'appeler une fonction sur des pointeurs NULL, ni de le faire du point de vue des performances.