web-dev-qa-db-ja.com

この関数には、すべての制御パスで明示的な戻り値がありますか?

私は Heaviside step function を持っています

template <typename T>
int h1(const T& t){
   if (t < 1){
       return 0;
   } else if (t >= 1){
       return 1;
   }
}

コードレビューで、私のレビュー担当者は、すべてのコントロールパスに明示的な戻り値はないことを教えてくれました。そして、コンパイラは私にも警告しません。しかし、私は同意しません。条件は相互に排他的です。これにどう対処しますか?

61

テンプレートの使用方法によって異なります。 intについては、大丈夫です。

ただしtdoubleに設定された値を持つIEEE754浮動小数点NaN型であり、t < 1 nor t >= 1trueなので、プログラム制御はifブロックの終わりに到達します!これにより、関数は明示的な値なしで戻ります。その動作は未定義です。

(より一般的なケースでは、T<および>=演算子は、すべての可能性をカバーしないような方法で、明示的なifなしでプログラム制御がreturnブロックの終わりに到達します。)

ここでの話の教訓は、どのブランチをデフォルトにするかを決定し、それをelseケースにすることです。

230
Bathsheba

コードが正しいからといって、それが改善されないわけではありません。正しい実行は最初品質のステップであり、最後ではありません。

if (t < 1) {
    return 0;
} else if (t >= 1){
    return 1;
}

上記はtのデータ型に対しては「正しい」ものであり、<および>=。でもこれは:

if (t < 1) {
    return 0;
}
return 1;

すべてのケースがカバーされていることを検査で確認しやすく、2番目の不必要な比較を完全に回避します(一部のコンパイラーは最適化されていない可能性があります)。コードは、コンパイラーだけでなく、10年後のあなたを含む人間によっても読み取られます。人間に休憩を与え、彼らの理解のためにもより簡単に書いてください。

13

前述のように、一部の特別な番号は両方とも<および>=ので、レビュアーは単に正しいです。

問題は、そもそもなぜこのようにコーディングしたいと思ったのですか?自分や他の人(コードを維持する必要のある人)の生活をこれほどまでに難しくすることを検討するのはなぜですか?あなたがそれを推測するのに十分賢いというだけの事実<および>=はすべてのケースをカバーする必要がありますが、必要以上にコードを複雑にする必要があるという意味ではありません。物理学の目的はコードにも当てはまります。物事を可能な限り単純化するが、単純化するのではありません(アインシュタインがこれを言ったと思います)。

考えてみてください。何を達成しようとしていますか? 「入力が1未満の場合は0を返し、そうでない場合は1を返します」のようなものでなければなりません。あなたがしたことは...と言って知能を追加することです...ああ、それはtが1以上の場合、1を返すことを意味します。それが良いことだと思うなら、私は自分で数年のコード保守を行うことをお勧めします。

それが私のレビューであった場合、私は別の発言をしたいと思います。 「if」ステートメントを使用すると、基本的にすべてのブランチで必要なことを実行できます。しかし、この場合、「何も」しません。必要なのは、t <1かどうかに応じて0または1を返すことだけです。そのような場合、 '?:'ステートメントはifステートメントよりもmuchより良く、読みやすいと思います。したがって:

return t<1 ? 0 : 1;

?:演算子はいくつかの企業で禁止されており、私はそれが恐ろしいことだと感じています。 ?:は通常、仕様と非常によく一致し、コードを非常に読みやすくすることができます(注意して使用した場合)...

8
Bert Bril