web-dev-qa-db-ja.com

ifステートメントを最初に定数に入れる理由は何ですか?

使用しているハードウェアインターフェイスのC++コードの例をいくつか見ていて、次の行に沿って多くのステートメントがあることに気づきました。

if ( NULL == pMsg ) return rv;

定数を最初に置くのは良い考えだと人々が言うのを聞いたことがあると思いますが、それはなぜですか?大きなステートメントがある場合、比較対象をすばやく確認できるようにするためですか、それともそれ以上のものがあるのでしょうか。

61
Jon Cage

比較(==)と割り当て(=)を混在させないようにします。

ご存知のように、定数に割り当てることはできません。試してみると、コンパイラーはエラーを出します。

基本的に、これは防御的なプログラミング手法の1つです。自分から身を守るため。

80
user151323

あなたが書くのを止めるには:

 if ( pMsg = NULL ) return rv;

間違って。ただし、優れたコンパイラはこれについて警告するので、ほとんどの人は読みにくいと感じるため、「定数優先」の方法を使用しません。

29
anon

私がいくつかのコメントに書いたことを明確にするために、ここに理由がありますnot C++コードでこれを行う。

たとえば、誰かが文字列クラスを作成し、キャスト演算子をconst char*に追加することにしました。

class BadString
{
public:
   BadString(const char* s) : mStr(s) { }

   operator const char*() const { return mStr.c_str(); }

   bool operator==(const BadString& s) { return mStr == s.mStr; }

   // Other stuff...

private:
   std::string mStr;
};

今、誰かが盲目的にconstant == variable「防御的」プログラミングパターンを適用します。

BadString s("foo");

if ("foo" == s) // Oops.  This compares pointers and is never true.
{
   // ...
}

これは、IMOであり、誤った割り当てよりも陰湿な問題です。コールサイトからは、明らかに何かが間違っていることがわからないためです。

もちろん、本当の教訓は次のとおりです。

  1. 独自の文字列クラスを作成しないでください。
  2. 特に(1)を実行する場合は、暗黙的なキャスト演算子を避けてください。

ただし、制御できないサードパーティのAPIを扱っている場合もあります。たとえば、WindowsCOMプログラミングで一般的な_bstr_t文字列クラスには、この欠陥があります。

8
jamesdlin

シングル=割り当てのバグを停止します。

例えば、

if ( NULL = pMsg ) return rv;

コンパイルされませんが、

if ( pMsg =  NULL) return rv;

コンパイルして頭痛の種になります

8
Dan McGrath

定数が最初の場合、定数に値を割り当てることは違法であるため、誤って=ではなく==を書き込んだ場合にコンパイラーは警告を出します。

7
liwp

彼らは、「割り当てと比較の混合を防ぐために」と言いました。

実際には、それはナンセンスだと思います。もしあなたがso左側に定数を置くことを忘れないように訓練されているなら、あなた間違いなく混同しないでしょう '= 'と' == '、あなたは? ;)

2

警告を出力するコンパイラは優れていますが、現実の世界では、警告をエラーとして扱う余裕がない人もいます。変数と定数の順序を逆にすると、この単純なスリップが常にエラーとして表示され、コンパイルが妨げられます。このパターンにすぐに慣れ、それが保護するバグは微妙なものであり、一度導入すると見つけるのが難しいことがよくあります。

2
SteveV

記事を忘れましたが、引用は次のようになりました。「== ";))を使用することを覚えているよりも、定数を最初に置くことを覚えている方が明らかに簡単です。

0
Joe