if(pointer!= NULL)ではなくif(pointer)を使用できますか?


171

NULL単に書いていないことへのポインタを確認しても安全ですか、それともif(pointer)使用する必要がありますif(pointer != NULL)か?


13
真実は、明示的なチェックを使用する場合、0またはに対してテストすることは同じくらい効果的であり、しばしば好まれnullptrます。(NULLC'ismであり、ヘッダーファイルを含める必要があります。)
cHao

5
@danijar最近のC ++ではnullptrを使用できます。
SurvivalMachine

9
@cHao「Cとの互換性を目指して」のポイントはどこにありますか?
qdii 2013

5
@danijar:はい。実装に依存するマクロであるNULLため、NULLあいまいな動作が発生する可能性があるため、今後はC ++で使用しないでください。
Alok Save

3
これは「if」のケースではありませんが、C ++のポインターで「NULL」と「0」を避ける必要がある理由については、このideoneライブデモを参照してください。ideone.com/ tbvXNs
kfsone

回答:


197

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

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


42

はい、できます。

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

これは、ブール変換句に含まれるC ++標準変換の一部です。

§4.12ブール変換

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


29

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

また、C ++ 11が導入されnullptrたことに注意してくださいNULL


10
ポインターはブール式ではありません。暗黙的に変換されます。理解するためにこの変換を覚えておかなければならないときに読んだ方がよい場合は、あなたの意見です。これはコーディングスタイルの1種類にすぎません。
13

7
@harperそれはコーディングスタイルだと言えるでしょう。しかし、整数もブール値ではないので、同じロジックをif(som_integer)vsに適用できますif(some_integer != 0)よね?私は避けるために好む0か、NULLif文で。
Yu Hao

13
それは単にコーディングスタイルの問題であることに同意します。私はif (pointer)自分を好むif (ptr != nullptr)ようになりましたが、私には完全に合法のようです。一方、書いたチームの誰かを見かけif (some_integer)たら、に変更させif (some_integer != 0)ます。ただし、これは自分の側で比較的恣意的な好みではないというふりはしません。ポインタと整数を同じように扱わないほうがよいだけです。
Joel

1
@YuHaoそして、それはコードスタイルなので、「それは好ましい」ではなく「私は好む」とは言いません。
13

5
@ franji1では、どうif(isReady) if(filePtr) if(serviceNo)ですか?意図的に不適切な変数名を作成しても、この場合はそれほど意味がありません。とにかく、私はすでにあなたの要点を理解し、それを理解しましたが、私自身のコーディングスタイルを自分で使用するように主張できます。
Yu Hao

13

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

私はいつも好むでしょう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はマクロなので、誰かが誤って他の値を使って再定義したとしたら。

6
==の代わりに=を使用すると、ほとんどの場合、if(NULL == ptr)を使用しなかった日のコンパイラ警告が生成されます
paulm

私がこの点を追加した@paulmは、ヨーダコンディションと呼ばれています。
Grijesh Chauhan 2013

2
(boolean expression)? true : false完全に無意味です。式はto trueまたはtoのいずれかを評価しfalseます。あなたが言うことは「それが本当なら、私に本当を与え、それが偽りなら、私に偽りを与えなさい」です。つまり、ブール式自体と完全に同等です。注node == NULLブール式です。ところで、あなたの2つの実装は互いに正反対を返します。どちらのあなたが欲しい!=最初に、または唯一の!第二インチ
celtschk 2013

ところで、=代わりに可能な対策の1つは、可能な限り==変数を作成するconstことです。たとえば、関数をとして定義するisEmnpy(node* const head) { ... }と、誤ってのnode = NULL代わりに書き込んだ場合、コンパイラはその関数のコンパイルを拒否しますnode == NULL。もちろん、これは実際に変更する必要がない変数に対してのみ機能します。
celtschk 2013

2
なぜなら、スマートポインタクラスは、暗黙的な変換を回避するT* get() const代わりに持っているoperator T*() constからです。しかし、彼らは持っていoperator bool() constます。
StellarVortex 2013

13

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

ここに画像の説明を入力してください


8

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


2

nullポインターの関連する使用例は次のとおりです。

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

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

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

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

    これは、短くてスコープセーフであるだけでなく、その意図もはるかに明確です。別のif条件でnullを確認すると、読者は「わかりましderived_ptrた。ここではnullにしないでください...」ヌル?」1行のバージョンは非常にはっきり言うのに対し、「あなたが安全にキャストすることができる場合base_ptrDerived*、そのためにそれを使用して...」。

    IMOは一般的にこれを回避する必要がありますが、ポインターを返す他の考えられる失敗した操作でも同じようにboost::optional機能します。ポインターではなく、操作が失敗する可能性がある場合は、「コンテナー」のようなものを使用することをお勧めします。

したがって、nullポインターの主な使用例を暗黙のキャストスタイルのバリエーションで常に記述する必要がある場合、一貫性の理由から常にこのスタイルを使用することをお勧めif(ptr)if(ptr!=nullptr)ます。つまり、overを推奨します。


私は広告で終わらなければならないのではないかと思いif(auto bla = ...)ます。構文は、実際には、そのような問題の実際の解決策であるパターンマッチングのほんの少し面倒な近似です。なぜ最初に何らかのアクション(ポインタのキャストなど)を強制してから、失敗の可能性があると見なすのでしょうか。つまり、それはばかげていますね。食べ物があり、スープを作りたいのです。果汁がやわらかい野菜の場合は、ジュースを抽出するタスクでアシスタントに渡します。あなたは最初にそれを見ません。ジャガイモを手に入れても、それをアシスタントに渡しますが、失敗のメモを付けて平手打ちします。ああ、命令型プログラミング!

はるかに良い:発生する可能性のあるすべてのケースをすぐに検討してください。その後、それに応じて行動します。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には、本当に深刻な失敗の可能性がある場合(および他の多くのもの)のための特別なツールもあります。モナドです。しかし、これはそれらを説明する場所ではありません。

⟨/広告⟩


1
私は実際に質問に答えるこの永遠のスクリードの1つの文しか見ることができません。
ローン侯爵2013

@EJP:質問を文字どおりに受けた場合(「使用できますか」)、明示的に回答されていません(答えは単に「はい」です)。私は、OP if(ptr)なく実際に使用する必要がある理由を適切に説明しようif(ptr != nullptr)としました。
レフトアラウンド約

1

はい、もちろん!実際、if(pointer)を記述する方が、if(pointer!= NULL)よりも便利な記述方法です。1。デバッグしやすい2.理解しやすい3.誤ってNULLの値が定義されている、その後、コードはクラッシュしません




-1

はい、 'IF'条件は内部の条件がtrueになった場合にのみ評価されるため、いつでもこれを実行できます。Cはブール型の戻り値を持たないため、条件がtrueの場合はゼロ以外の値を返し、 'IF'の条件がfalseの場合は常に0を返します。デフォルトで返されるゼロ以外の値は1です。したがって、コードを作成する両方の方法が正しい一方で、常に2番目の方法を優先します。


1
私が正しく覚えていれば、デフォルトのゼロ以外の値は未定義です。
ローン侯爵2013

-1

経験則として、あなたのif式を次のように書き直すことができれば

const bool local_predicate = *if-expression*;
if (local_predicate) ...

警告が発生しないように、それがif-expressionの推奨スタイルである必要があります。(古いC BOOL#define BOOL int)をC ++ に割り当てると、boolポインタはもちろんのこと、警告が表示されます。)


-1

「それは安全ですか?。」言語標準と生成されたコードに関する質問です。

「いい練習ですか?」発言を任意の人間の読者がどの程度理解しているかについての質問です。この質問をしている場合は、「安全な」バージョンは将来の読者やライターにとって不明確であることが示唆されています。


私の意図は、それが安全かどうかを尋ねることでした。したがって、私はその表現を使用しました。しかし、あなたがここに書いたことは質問に対する答えではありません。代わりに、質問の下のコメントにする必要があります。回答を削除して、質問の下にコメントを追加できます。
danijar 2013

@danijar StackOverflowを初めて使用して「コメント」セクションを検索したが、成功しなかったのを覚えていませんか?7人の評判を持つ人はそれを行うことができません。
Broxzier 2013

@JimBalter他の人がそうしているのを見ることができるので、これは非常に混乱します。私がSOを初めて使用したとき、誰かが私にそうしたことを非難しました。
Broxzier 2013

@JimBalter私は殺害したり盗んだりしていません。私はダニエルフレッド・ミッチェルが新しいユーザーでコメントを投稿することができなかったと話していました。
Broxzier 2013

@JimBalterあなたが今日始めたもの。また、あなたが代わりに理解していないものです。そのコメントはこれの混乱をサポートするだけです。
Broxzier 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.