这个函数在所有控制path上都有明确的返回值吗?
我有一个Heaviside步骤函数集中于任何数据types,我编码使用:
template <typename T> int h1(const T& t){ if (t < 1){ return 0; } else if (t >= 1){ return 1; } }
在代码审查中,我的审稿人告诉我,在所有的控制path上都没有明确的回报。 而编译器也不会警告我。 但我不同意; 条件是相互排斥的。 我如何处理这个?
这取决于如何使用模板。 对于一个int
,你很好。
但是 ,如果t
是一个值为NaN
的IEEE754浮点double
精度types,那么t < 1
和t >= 1
都不为true
,所以程序控制到达if
块的末尾! 这导致函数返回没有显式值; 其行为是不确定的。
(在更一般的情况下,如果T
不会覆盖所有的可能性, T
重载<
和>=
运算符,程序控制将在没有显式return
到达if
块的末尾。
这里故事的寓意是决定哪个分支应该是默认分支,并使其成为else
分支。
只是因为代码是正确的,这并不意味着它不会更好。 正确执行是质量的第一步,而不是最后一步。
if (t < 1) { return 0; } else if (t >= 1){ return 1; }
以上对任何数据types的“正确”比对<
和>=
理性行为都是正确的。 但是这个:
if (t < 1) { return 0; } return 1;
通过检查可以更容易地看到每个案例都被覆盖,并避免了第二次不必要的比较(有些编译器可能没有优化出来)。 代码不仅可以被编译器读取,而且可以被人类读取,包括10年之后。 让人类rest一下,写出更简单的理解。
如上所述,一些特殊的数字可以是<
和>=
,所以您的评论者是正确的。
问题是:是什么让你想要这样编码呢? 为什么你甚至考虑让自己和别人(需要维护你的代码的人)的生活变得如此艰难? 只要你足够聪明就可以推断出<
和>=
应该涵盖所有的情况并不意味着你必须使代码比必要的更加复杂。 物理学也适用于代码:尽可能简单,但并不简单(我相信爱因斯坦说过)。
想想看。 你想达到什么目的? 必须是这样的:'如果input小于1,则返回0,否则返回1。 你所做的是通过说…增加智力哦,但是这意味着如果t大于或等于1,我返回1.这种不必要的'x暗示y'代表维护者需要额外的思考工作。 如果你认为这是一件好事,我build议你自己做几年的代码维护。
如果是我的评论,我会再说一次。 如果你使用“if”语句,那么你基本上可以在所有分支中做任何你想要的事情。 但在这种情况下,你不会做任何事情。 所有你想要做的是返回0或1取决于是否t <1。 在这些情况下,我认为'?:'声明比if
声明更好,更可读。 从而:
return t<1 ? 0 : 1;
我知道一些公司禁止?:
运营商,我觉得这是一件可怕的事情。 ?:
通常与规格匹配得更好,并且可以使代码更容易阅读(如果小心使用)…