对于任何数据类型,我都有Heaviside step function以统一为中心,我使用以下编码:
template <typename T>
int h1(const T& t){
if (t < 1){
return 0;
} else if (t >= 1){
return 1;
}
}
在代码审查中,我的审稿人告诉我,所有控制路径都没有明确的回报。编译器也没有警告我。但我不同意;条件相互排斥。我该如何处理?
答案 0 :(得分:229)
这取决于模板的使用方式。对于int
,你很好。
但是,如果t
是IEEE754浮点double
类型,其值设置为NaN
,则t < 1
和{{1}都不是是t >= 1
,因此程序控制到达true
块的末尾!这会导致函数返回而没有显式值;其行为未定义。
(在更一般的情况下,if
重载T
和<
运算符的方式不能涵盖所有可能性,程序控制将到达{ {1}}阻止没有明确的>=
。)
这里的故事的寓意是决定哪个分支应该是默认的,并使那个分支成为if
个案例。
答案 1 :(得分:13)
仅仅因为代码是正确的,这并不意味着它不会更好。正确执行是质量的第一个步骤,而不是最后一步。
if (t < 1) {
return 0;
} else if (t >= 1){
return 1;
}
对于t
的任何数据类型而言,上述内容对于<
和>=
的理智行为都是“正确的”。但是这个:
if (t < 1) {
return 0;
}
return 1;
通过检查更容易看出每个案例都被覆盖,并且完全避免了第二个不需要的比较(某些编译器可能没有优化)。代码不仅由编译器读取,而且由人类读取,包括10年后的人。给人类一个休息时间,并为他们的理解更简单地写作。
答案 2 :(得分:8)
如上所述,某些特殊号码可以是<
和>=
,因此您的审核人员就是正确的。
问题是:是什么让你想要首先像这样编码?为什么你甚至考虑让自己和他人(需要维护代码的人)的生活如此艰难?事实上,你足够聪明地推断出<
和>=
应涵盖所有情况并不意味着你必须使代码更加复杂而不必要。物理学也适用于代码:尽可能简单,但不简单(我相信爱因斯坦这样说)。
想一想。你想要实现什么目标?必须是这样的:'如果输入小于1则返回0,否则返回1。你所做的就是通过说...哦,但这意味着如果t大于或等于1则返回1.这种不必要的'x暗示y'需要代表维护者进行额外的思考工作。如果您认为这是一件好事,我建议您自己进行几年的代码维护。
如果是我的评论,我会再说一遍。如果您使用'if'语句,那么您基本上可以在所有分支中执行任何操作。但在这种情况下,你不做“任何事情”。您要做的只是返回0或1,具体取决于是否t <1。在这些情况下,我认为'?:'语句比<{1}}语句更强大,更可读。因此:
if
我知道某些公司禁止使用return t<1 ? 0 : 1;
运营商,我觉得这很糟糕。 ?:
通常与规范匹配得更好,它可以使代码更容易阅读(如果小心使用)......