42 votes

Est-il sûr de #define NULL nullptr ?

J'ai vu la macro ci-dessous dans de nombreux fichiers d'en-tête les plus importants :

#define NULL 0  // C++03

Dans tout le code, NULL et 0 sont utilisés de manière interchangeable. Si je le change en.

#define NULL nullptr  // C++11

Aura-t-il des effets secondaires ? Je pense que le seul (bon) effet secondaire est que l'usage suivant deviendra mal formé ;

int i = NULL;

40voto

Xeo Points 69818

J'ai vu la macro ci-dessous dans le fichier d'en-tête le plus élevé :

Vous ne devriez pas avoir vu cela, la bibliothèque standard le définit dans <cstddef> (et <stddef.h> ). Et, IIRC, selon la norme, la redéfinition des noms définis par les fichiers d'en-tête standard entraîne un comportement non défini. Donc, d'un point de vue purement standard, vous ne devriez pas le faire.


J'ai vu des gens faire ce qui suit, pour n'importe quelle raison à laquelle leur esprit brisé a pensé :

struct X{
  virtual void f() = NULL;
}

(Comme dans [incorrect] : "mettre le pointeur de la table virtuelle à NULL ")

Ceci n'est valable que si NULL est défini comme suit 0 parce que = 0 est le jeton valide pour les fonctions purement virtuelles ( §9.2 [class.mem] ).

Cela dit, si NULL était correctement utilisé comme une constante à pointeur nul, alors rien ne devrait casser.

Attention toutefois, même si elle semble être utilisée correctement, elle peut changer :

void f(int){}
void f(char*){}

f(0); // calls f(int)
f(nullptr); // calls f(char*)

Cependant, si c'était le cas, il était certainement cassé de toute façon.

14voto

spraff Points 10492

Le mieux est de chercher et de remplacer NULL avec nullptr dans tout le code.

C'est peut-être syntaxiquement sûr, mais où mettriez-vous l'élément #define ? Cela crée des problèmes d'organisation du code.

7voto

James Kanze Points 96599

Non. Vous n'êtes pas autorisé à (re)définir des macros standard. Et si vous voyez

#define NULL 0

en haut de n'importe quel fichier autre qu'un en-tête standard (et même là, elle devrait être dans des gardes d'inclusion, et typiquement dans des gardes supplémentaires aussi ), alors ce fichier est cassé. Supprimez-le.

Notez que les bons compilateurs définissent généralement NULL avec quelque chose comme :

#define NULL __builtin_null

pour accéder à un compilateur qui déclenchera un avertissement s'il est utilisé dans un contexte non pointeur. utilisé dans un contexte de non-pointeur.

4voto

Mike Seymour Points 130519

Vous ne devriez pas le définir du tout, sauf si vous écrivez votre propre version de <cstddef> il ne devrait certainement pas se trouver dans "de nombreux fichiers d'en-tête supérieurs".

Si vous implémentez votre propre bibliothèque standard, la seule exigence est la suivante

18.2/3 La macro NULL est une constante de pointeur nul C++ définie par l'implémentation.

donc soit 0 ou nullptr est acceptable, et nullptr est préférable (si votre compilateur le supporte) pour la raison que vous indiquez.

4voto

Kaz Dragon Points 3460

Peut-être pas.

Si vous avez un format particulier de comportement de surcharge :

void foo(int);
void foo(char*);

Ensuite, le comportement du code :

foo(NULL);

changera selon que NULL est changé en nullptr ou non.

Bien sûr, il y a une autre question à savoir s'il est sûr d'écrire un code tel que celui présent dans cette réponse...

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