web-dev-qa-db-fra.com

Puis-je utiliser if (pointeur) au lieu de if (pointeur! = NULL)?

Est-il prudent de vérifier un pointeur pour ne pas être NULL en écrivant simplement if(pointer) ou dois-je utiliser if(pointer != NULL)?

154
danijar

Vous pouvez; le pointeur null est implicitement converti en boolean false tandis que les pointeurs non null sont convertis en true. Du standard C++ 11, section sur Conversions booléennes:

Une valeur prédéfinie d'arithmétique, une énumération non réduite, un pointeur ou un pointeur sur un type de membre peut être convertie en un prvalue de type bool. Une valeur nulle, une valeur de pointeur nulle ou une valeur de pointeur de membre nul est convertie en false; toute autre valeur est convertie en true . Une valeur de type std::nullptr_t peut être converti en une valeur de type bool ; la valeur résultante est false .

171
Joni

Oui vous pourriez.

  • Un pointeur nul est converti implicitement en faux
  • un pointeur non nul est converti en true.

Cela fait partie de la conversion standard C++, qui relève de la clause Boolean conversion:

§ 4.12 Conversions booléennes

Une valeur prédéfinie d'arithmétique, énumération non rognée, pointeur , ou un pointeur sur un type de membre peut être convertie en une valeur de type bool. Une valeur nulle, une valeur de pointeur nulle ou une valeur de pointeur de membre nul est convertie en false; toute autre valeur est convertie en true. Une valeur de type std :: nullptr_t peut être convertie en une valeur de type bool; la valeur résultante est false.

35
billz

Oui, vous pouvez. En fait, je préfère utiliser if(pointer) car il est plus simple de lire et d’écrire une fois que vous vous y êtes habitué.

Notez également que C++ 11 a introduit nullptr, qui est préférable à NULL.

29
Yu Hao

La question est répondue, mais je voudrais ajouter mes points. 

Je préférerai toujours if(pointer) au lieu de if(pointer != NULL) et if(!pointer) au lieu de if(pointer == NULL)

  • C'est simple, petit 
  • Moins de chances d'écrire un code buggy, supposons si j'ai mal orthographié l'opérateur de contrôle d'égalité == avec =
    if(pointer == NULL) peut être mal orthographié if(pointer = NULL) Donc, je vais l'éviter, le mieux est simplement if(pointer).
    (J'ai aussi suggéré une condition Yoda dans une réponse , mais c'est différent

  • De même pour while (node != NULL && node->data == key), j'écrirai simplement while (node && node->data == key) qui m'est plus évident (montre que l'utilisation d'un court-circuit).

  • (peut être une raison stupide) Parce que NULL est une macro, supposons que quelqu'un redéfinisse par erreur avec une autre valeur.
11
Grijesh Chauhan

La vérification explicite de la valeur NULL pourrait donner au compilateur un indice sur ce que vous tentez de faire, ce qui peut également entraîner moins de risques d’erreurs.

 enter image description here

9
Minqi Pan

Oui, vous pouvez. La possibilité de comparer implicitement des valeurs à des zéros a été héritée de C et existe dans toutes les versions de C++. Vous pouvez également utiliser if (!pointer) pour vérifier les pointeurs pour NULL.

8
dasblinkenlight

Les cas d'utilisation pertinents pour les pointeurs nuls sont

  • Redirection vers quelque chose comme un nœud d'arbre plus profond, qui peut ne pas exister ou qui n'a pas encore été lié. C'est quelque chose que vous devriez toujours garder étroitement encapsulé dans une classe dédiée, de sorte que la lisibilité ou la concision ne soit pas un si gros problème ici.
  • Dynamique jette. Le fait de fondre un pointeur de classe de base sur un pointeur de classe dérivée particulier (ce que vous devriez à nouveau essayer d'éviter, mais que vous jugez parfois nécessaire) réussit toujours, mais aboutit à un pointeur nul si la classe dérivée ne correspond pas. Une façon de vérifier c'est

    Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
    if(derived_ptr != nullptr) { ... }
    

    (ou, de préférence, auto derived_ptr = ...). Maintenant, ceci est mauvais, car il laisse le pointeur dérivé (éventuellement non valide, null) en dehors du champ du bloc de sécurité if. Ce n'est pas nécessaire, car C++ vous permet d'introduire des variables booléennes convertibles dans une variable if- :

    if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }
    

    ce qui est non seulement plus court et sûr, mais aussi beaucoup plus clair dans son intention: lorsque vous recherchez la valeur null dans une condition if distincte, le lecteur se demande "ok, donc derived_ptr ne doit pas être null ici ... eh bien, pourquoi serait-il nul? " Alors que la version à une ligne dit très clairement "si vous pouvez transtyper base_ptr en Derived* en toute sécurité, utilisez-le pour ...".

    La même chose fonctionne aussi bien pour toute autre opération d'échec possible qui retourne un pointeur, mais IMO évite généralement ceci: il est préférable d'utiliser quelque chose comme boost::optional en tant que "conteneur" pour les résultats d'opérations éventuellement en échec, plutôt que des pointeurs.

Donc, si le cas d'utilisation principal pour les pointeurs nuls doit toujours être écrit dans une variante du style de diffusion implicite, je dirais que c'est bien pour des raisons de cohérence d'utiliser toujours utiliser ce style, c'est-à-dire if(ptr) sur if(ptr!=nullptr).


J'ai bien peur de devoir terminer par une publicité: la syntaxe if(auto bla = ...) n'est en réalité qu'une approximation un peu lourde de la solution real à ces problèmes: pattern matching . Pourquoi voudriez-vous d'abord forcer une action (comme lancer un pointeur) et ensuite considérer qu'il pourrait y avoir un échec ... Je veux dire, c'est ridicule, n'est-ce pas? C'est comme si tu avais des aliments et que tu voulais faire de la soupe. Vous le remettez à votre assistant avec la tâche d'extraire le jus, s'il s'agit d'un légume doux. Vous ne le regardez pas d'abord. Quand vous avez une pomme de terre, vous la donnez toujours à votre assistant, mais il vous la gifle avec une note d'échec. Ah, la programmation impérative!

Bien mieux: considérez tout de suite tous les cas que vous pourriez rencontrer. Alors agissez en conséquence. Haskell:

makeSoupOf :: Foodstuff -> Liquid
makeSoupOf p@(Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
 | isSoft vegetable  = squeeze vegetable <> salt
makeSoupOf stuff  = boil (throwIn (water<>salt) stuff)

Haskell dispose également d'outils spéciaux pour les cas où il existe une possibilité sérieuse d'échec (ainsi que pour tout un tas d'autres éléments): les monades. Mais ce n’est pas le lieu d’expliquer cela.

⟨/publicité⟩

2
leftaroundabout

Oui. En fait, vous devriez. Si vous vous demandez s'il crée une erreur segmentation , ce n'est pas le cas.

0
darshandzend

oui bien sûr! en fait, écrire si (pointeur) est un moyen plus pratique d’écrire que si (pointeur! = NULL) car: il est facile de déboguer 2. facile à comprendre 3. si accidentellement, la valeur de NULL est définie, le code ne plantera pas non plus

0
Palak Jain