私は最近、入力ミスが原因であるコードのバグを見つけ出すのに時間を費やしました:
if (a=b)
それ以外の:
if (a==b)
ステートメント内の変数に値を割り当てたい特定のケースがあるかどうかif
、またはそうでない場合、コンパイラが警告またはエラーをスローしないのはなぜですか?
私は最近、入力ミスが原因であるコードのバグを見つけ出すのに時間を費やしました:
if (a=b)
それ以外の:
if (a==b)
ステートメント内の変数に値を割り当てたい特定のケースがあるかどうかif
、またはそうでない場合、コンパイラが警告またはエラーをスローしないのはなぜですか?
代入演算子は、割り当てられた値の値を返します。したがって、次のような状況で使用できます。
if (x = getMyNumber())
x
によって返される値を代入しgetMyNumber
、それがゼロでないかどうかを確認します。
それは避けてください。これを理解するのを助けるために例を挙げました。
編集: ただの提案を追加します。
このようなバグを回避するには、一部の拡張まで、if 条件をif(NULL == ptr)
代わりに書く必要if (ptr == NULL)
があります。なぜなら、等値チェック演算子のスペルを operator と間違える==
と=
、コンパイルは左辺値エラーを でスローしますがif (NULL = ptr)
、if (res = NULL)
コンパイラによって渡されます (これはあなたが意味するものではありません)。実行時のコードのバグのままです。
この種のコードに関する批判も読むべきです。
最近、これが役立つケースに遭遇したので、投稿することにしました。
1 つの if で複数の条件をチェックし、いずれかの条件が true の場合にエラー メッセージを生成するとします。エラーの原因となった特定の条件をエラー メッセージに含めたい場合は、次のようにします。
std::string e;
if( myMap[e = "ab"].isNotValid() ||
myMap[e = "cd"].isNotValid() ||
myMap[e = "ef"].isNotValid() )
{
// here, e has the key for which the validation failed
}
したがって、2 番目の条件が true と評価される場合、e は "cd" と等しくなります。||
これは、標準で義務付けられている短絡動作によるものです (過負荷でない限り)。短絡の詳細については、この回答を参照してください。
c++17 では、以下を使用できます。
if (<initialize> ; <conditional_expression>) { <body> }
for ループ イテレータ初期化子に似ています。
次に例を示します。
if (Employee employee = GetEmployee(); employee.salary > 100) { ... }
で割り当てを行うことif
はかなり一般的なことですが、人々が偶然にそれを行うことも一般的です。
通常のパターンは次のとおりです。
if (int x = expensive_function_call())
{
// ...do things with x
}
アンチパターンは、誤って物事に割り当てている場所です。
if (x = 1)
{
// Always true
}
else
{
// Never happens
}
定数または値を最初に配置することで、これをある程度回避できるためconst
、コンパイラはエラーをスローします。
if (1 = x)
{
// Compiler error, can't assign to 1
}
=
対==
は、目を養う必要があるものです。私は通常、演算子の周りに空白を配置して、どの操作が実行されているかをより明確にします。一目でlongname=longername
よく似ていますが、それ自体は明らかに異なります。longname==longername
=
==