Pourquoi ne pas appeler nullptr NULL?
En C++11, le mot clé nullptr
a été ajouté en tant que constante de pointeur null plus sûre, puisque la définition commune précédente de NULL
as 0 a quelques problèmes.
Pourquoi le Comité de normalisation a-t-il choisi de ne pas appeler la nouvelle constante de pointeur null NULL
, ou de déclarer que NULL
devrait être #define
D à nullptr
?
7 réponses
Stephan T. Lavavej (membre du comité de normalisation C++) a expliqué qu'une fois dans un parler (55:35):
Alors qu'une implémentation est autorisée à #define NULL nullptr
, elle casserait pas mal d'utilisations comme
int i = NULL;
Et apparemment il y en a beaucoup. Donc, ils ne pouvaient pas forcer le changement.
nullptr
est de Type de pointeur , tandis que NULL
a tendance à être entier, et parfois dans les fonctions surchargées, vous devez être clair que vous utilisez un pointeur et non un entier - c'est quandnullptr
est utile.
Donc, pour vraiment répondre à votre question, NULL
et nullptr
servent à des fins différentes et redéfinir l'un à l'autre va probablement casser beaucoup de choses dans les bases de code déjà existantes.
À côté de cela,
Vérifiez ceci depuis Bjarne Le site de Stroustrup
Devrais-je utiliser NULL ou 0?
En C++, La définition de NULL est 0, donc il n'y a qu'une esthétique différence. Je préfère éviter les macros, donc j'utilise 0. Un autre problème avec NULL est que les gens croient parfois à tort que c'est différent de 0 et / ou pas un entier. Dans le code pré-standard, NULL était / est parfois défini à quelque chose de inapproprié et donc devait/doit être éviter. C'est moins fréquent de nos jours. Si vous avoir à nommer le null pointeur, appelez-le nullptr; c'est ce qu'on appelle en C++11. Puis, "nullptr" sera un mot-clé.
Sans réellement participer à la discussion au Comité des normes, c'est difficile à dire avec certitude, mais je pense que cela casserait un code qui utilise NULL
dans un sens où nullptr
n'est pas suffisamment compatible. Et briser l'ancien code n'est jamais une bonne idée.
NULL
n'est pas sécurisé. Pour une raison historique, il a été défini comme 0 sans casting, et le compilateur silence avertissement du numéro de casting au pointeur sur ce Zéro spécial.
Pour l'instant, vous pouvez faire:
void* p = 0;
Mais pas ceci sans casting implicite:
void* p = 1234;
L'effet secondaire est qu'il peut être abusé en tant que valeurs numériques, comme l'autre réponse mentionnée.
nullptr
améliorez ceci en l'appliquant est un pointeur, vous ne pouvez pas l'affecter à un entier.
Puisque le comportement est modifié, un nouveau nom est créé pour la compatibilité descendante.
Notez également que, nullptr
est géré par le compilateur, sa valeur réelle n'est pas exposée à l'utilisateur (comme zéro dans le cas de NULL
). Il est beaucoup plus facile d'avoir une valeur dépendante de l'architecture, par exemple 0xdeadbeef
, sans affecter la logique de code du programmeur.
Pourquoi le Comité de normalisation a-t-il choisi de ne pas appeler la nouvelle constante de pointeur nul NULL
Vraisemblablement parce que le nouveau pointeur null est un mot-clé, et les mots-clés ne peuvent pas être #defined
, donc l'appeler NULL
aurait rendu l'inclusion de tout en-tête C probablement mal formée.
, Ou déclarer qu' NULL
devrait être #defined
à nullptr
?
Le Comité de normalisation autorise NULL
à être #defined
à nullptr
, mais il ne l'exige pas.
C++11 18.2 Types [soutien.types] / 2 : La macro
NULL
est une constante de pointeur null c++ définie par l'implémentation dans cette norme internationale.C++11 4.10 conversions de pointeur [conv.ptr] / 1 : Une constante de pointeur null est une expression constante intégrale (5.19) prvalue de type entier qui évalue à zéro ou une prvalue de type
std::nullptr_t
.
Rétro-compatibilité n'est pas un problème ici, toute utilisation de NULL
, ce qui suppose qu'il s'agit d'une forme d'entier 0
n'est pas standard conforme. Les implémentations peuvent choisir de ne pas le faire pour tolérer ce genre de comportement diabolique.
Je vais démontrer un cas où la décision de définir nullptr comme un type différent aide à prévenir les bugs.
Considérez ces fonctions:
void foo(int);
void foo(char *);
int main()
{
foo(NULL); // oops
}
En C++98, le code ci-dessus appelle la fonction foo(int), car NULL est remplacé par 0, ce qui n'est probablement pas ce que vous vouliez.
, Mais si vous appelez foo(nullptr), il appelle la bonne -- foo(char*).
Le {[0] } est introduit pour la sécurité des types et pour la clarté (probablement pour arrêter l'initialisation des types non-pointeurs en utilisant NULL
).
Le NULL
(type int) n'est pas changé en nullptr
(Type de pointeur) pour éviter toute confusion et pour assurer la compatibilité ascendante.
Ainsi, le train de pensée du Comité standard est probablement lié à la transition en douceur de l'ancienne à la nouvelle notation sans causer d'ambiguïtés ni freiner tout code déjà existant.