web-dev-qa-db-ja.com

if(pointer!= NULL)の代わりにif(pointer)を使用できますか?

単にif(pointer)と書くことでNULLでないことを指すポインターをチェックするのは安全ですか、それともif(pointer != NULL)を使用する必要がありますか?

160
danijar

あなたはできる; NULLポインターは暗黙的にブール値のfalseに変換されますが、非NULLポインターはtrueに変換されます。 C++ 11標準のブール変換:に関するセクション

算術のprvalue、スコープのない列挙、ポインター、またはメンバー型へのポインターは、bool型のprvalueに変換できます。ゼロ値、nullポインター値、またはnullメンバーポインター値はfalseに変換されます。その他の値はtrueに変換されます。タイプstd::nullptr_tのprvalueは、タイプboolのprvalueに変換できます。結果の値はfalseです。

175
Joni

はい、できます。

  • NULLポインターは暗黙的にfalseに変換されます
  • nULL以外のポインターはtrueに変換されます。

これは、C++標準変換の一部であり、ブール変換句に該当します。

§4.12ブール変換

算術のprvalue、有効範囲なし列挙、pointer、またはメンバー型へのポインターは、bool型のprvalueに変換できます。 ゼロ値、nullポインター値、またはnullメンバーポインター値はfalseに変換されます。他の値はtrueに変換されます。 std :: nullptr_t型のprvalueはbool型のprvalueに変換できます。 ;結果の値はfalseです。

38
billz

はい、できます。実際、慣れると、読み書きが簡単になるため、if(pointer)を使用することを好みます。

また、C++ 11にはnullptrよりも優先されるNULLが導入されていることに注意してください。

29
Yu Hao

質問に回答しましたが、ポイントを追加したいと思います。

私は常にif(pointer)の代わりにif(pointer != NULL)if(!pointer)の代わりにif(pointer == NULL)を好むでしょう:

  • シンプルで小さい
  • バグチェックコードを記述する可能性が低くなります。等値チェック演算子==のスペルを=と間違えた場合
    if(pointer == NULL)はつづりが間違っている可能性がありますif(pointer = NULL)だからそれは避けます。最善はif(pointer)です。
    (私はいくつかの 1つの答えでヨーダの条件 を提案しましたが、それは別の問題です)

  • while (node != NULL && node->data == key)についても同様に、while (node && node->data == key)を書くだけです。これは私にとってより明白です(短絡を使用することを示しています)。

  • (愚かな理由かもしれません)NULLはマクロなので、あるものが他の値と誤って再定義されたと仮定した場合。
12
Grijesh Chauhan

NULLを明示的にチェックすると、コンパイラに何をしようとしているかのヒントが提供され、エラーが発生しにくくなります。

enter image description here

10
Minqi Pan

はい、できます。値をゼロと暗黙的に比較する機能はCから継承されており、C++のすべてのバージョンにあります。 if (!pointer)を使用して、ポインターのNULLを確認することもできます。

8
dasblinkenlight

NULLポインターの関連するユースケースは次のとおりです。

  • 存在しないか、まだリンクされていない、より深いツリーノードのようなものへのリダイレクト。これは常に専用のクラスに密接にカプセル化する必要があるため、ここでは読みやすさや簡潔さはそれほど重要ではありません。
  • ダイナミックキャスト。基本クラスポインターを特定の派生クラス1(再度回避しようとする必要がありますが、必要な場合があります)へのキャストは常に成功しますが、派生クラスが一致しない場合はNULLポインターになります。これを確認する1つの方法は

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

    (または、できればauto derived_ptr = ...)。さて、これは悪いです。なぜなら、それは安全ガードifブロックのスコープ外に(おそらく無効、つまりnull)派生ポインタを残すからです。 C++ではブール変換可能な変数を導入できるため、これは必要ありませんif- condition内

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

    これは短くてスコープセーフであるだけでなく、意図がはるかに明確です:別のif条件でnullをチェックすると、読者は「OK、だからderived_ptrはnullであってはいけません...まあ、なぜnullでしょうか?」一方、1行バージョンでは、「base_ptrを安全にDerived*にキャストできる場合は、それを使用して...」と非常にわかりやすく説明しています。

    同じことは、ポインターを返す他の可能性のある障害操作でも同様に機能しますが、IMOでは一般的にこれを避ける必要があります。ポインターではなく、失敗する可能性のある操作の結果の「コンテナー」としてboost::optionalのようなものを使用することをお勧めします.

したがって、nullポインターの主なユースケースを暗黙的なキャストスタイルのバリエーションで常に記述する必要がある場合、一貫性の理由でalwaysこのスタイルを使用する、つまりI ' d if(ptr)よりもif(ptr!=nullptr)を推奨します。


私は広告で終わらせなければならないのではないかと思います:if(auto bla = ...)構文は、実際にはrealのような問題の解決法に少し面倒な近似です:pattern matching。最初に何らかのアクション(ポインターのキャストなど)を強制してから、失敗があるかもしれないと考えるのはなぜですか?つまり、それはばかげていますね。食べ物があり、スープを作りたいみたいです。柔らかい野菜である場合は、ジュースを抽出するタスクをアシスタントに渡します。最初にそれを見ないでください。あなたがジャガイモを持っているとき、あなたはまだあなたのアシスタントにそれを与えますが、彼らは失敗のメモであなたの顔にそれを平手打ちします。ああ、命令型プログラミング!

はるかに良い:あなたが遭遇する可能性のあるすべてのケースをすぐに検討してください。その後、それに応じて行動します。ハスケル:

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には、実際に重大な障害の可能性がある場合(および他の多くの場合)のモナド用の特別なツールもあります。しかし、これはそれらを説明する場所ではありません。

⟨/advert⟩

2
leftaroundabout

はい。実際、そうすべきです。 セグメンテーションフォールト を作成するかどうか疑問に思っている場合は、作成しません。

0
darshandzend

はい、もちろん!実際、if(pointer)の書き込みは、if(pointer!= NULL)よりも便利な書き込み方法です。1。デバッグが簡単2.わかりやすい3.誤ってNULLの値が定義されている場合、また、コードはクラッシュしません

0
Palak Jain