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