此函数是不是在所有控制路径上都有明确的返回值?
Posted
技术标签:
【中文标题】此函数是不是在所有控制路径上都有明确的返回值?【英文标题】:Does this function have explicit return values on all control paths?此函数是否在所有控制路径上都有明确的返回值? 【发布时间】:2018-03-10 02:16:24 【问题描述】:我有一个Heaviside step function,它以任何数据类型的统一为中心,我使用以下代码对其进行了编码:
template <typename T>
int h1(const T& t)
if (t < 1)
return 0;
else if (t >= 1)
return 1;
在代码审查中,我的审查者告诉我,并非所有控制路径都明确返回。编译器也没有警告我。但我不同意;条件是互斥的。我该如何处理?
【问题讨论】:
return t >= 1;
在没有分支的情况下给你同样的...
出于兴趣,为什么这个函数需要模板化?您是否真的将它用于不同的类型?
@KobyDuck 不能保证return a+b;
不会分支,或者return 1;
不会分支。 C++ 对“将代码分支”做出零保证。您可以消除抽象机中的分支,并且可以使用编译器已知的习语在可用时发出无分支指令。
考虑在特殊情况下抛出domain_error
。
你有这么关心的评论者吗?数一数你的祝福!
【参考方案1】:
这取决于模板的使用方式。对于int
,你很好。
但是,如果t
是IEEE754浮点型double
,其值设置为NaN
,则t < 1
和t >= 1
都不是true
,所以程序控制到达if
块的末尾!这会导致函数在没有显式值的情况下返回;其行为未定义。
(在更一般的情况下,T
重载 <
和 >=
运算符以不涵盖所有可能性,程序控制将到达 if
块的末尾而没有显式return
.)
这里故事的寓意是决定哪个分支应该是默认的,并将那个分支设为else
的情况。
【讨论】:
【参考方案2】:仅仅因为代码是正确的,并不意味着它不可能更好。正确执行是质量的第一步,而不是最后一步。
if (t < 1)
return 0;
else if (t >= 1)
return 1;
以上对于t
的任何数据类型都是“正确的”,而不是<
和>=
的正常行为。但是这个:
if (t < 1)
return 0;
return 1;
通过检查更容易看出每种情况都已涵盖,并且完全避免了第二次不必要的比较(某些编译器可能没有优化)。代码不仅可以被编译器读取,还可以被人类读取,包括 10 年后的你。让人类休息一下,写得更简单,以供他们理解。
【讨论】:
我知道你想说什么(有一个赞成票),但这里暗示 IEEE754 类型不是“理智的”。这是你的意思吗?我也很想看到一个编译器优化第二个条件检查的例子。 @Bathsheba:我不认为说NaN
不是“理智的”是完全不合理的- numeric 类型的值不是 number,因此类型没有排序?显然我知道它为什么存在:争论不是float
应该 做这样的事情,而只是它导致了无意义的排序操作。我想有人可以说这样表达是不合理的,因为社会普遍使用精神疾病作为任何困难或意外的类比的内在能力。
@Bathsheba 我认为partially ordered set 理智(它允许x<1
和x>=1
都是错误的),但我认为IEEE 浮动是疯狂的,因为==
不是等价关系并且比较不'不符合部分排序的要求。
@Bathsheba,gcc -O2(和 -O3)删除了与整数 t 的第二次比较。【参考方案3】:
如前所述,一些特殊的数字可以是<
和>=
,所以你的审阅者是对的。
问题是:最初是什么让您想这样编写代码?为什么你甚至考虑让自己和他人(需要维护你的代码的人)的生活变得如此艰难?仅仅你足够聪明地推断出<
和>=
应该涵盖所有情况并不意味着你必须使代码变得比必要的更复杂。物理学也适用于代码:让事情尽可能简单,但不是更简单(我相信爱因斯坦是这么说的)。
考虑一下。你想达到什么目的?必须是这样的:'如果输入小于 1,则返回 0,否则返回 1。您所做的是通过说...增加智能...哦,但这意味着如果 t 大于或等于 1,我将返回 1。这种不必要的“x 意味着 y”需要代表维护者进行额外的思考工作。如果您认为这是一件好事,我建议您自己进行几年的代码维护。
如果这是我的评论,我会再发表评论。如果你使用“if”语句,那么你基本上可以在所有分支中做任何你想做的事情。但在这种情况下,你什么都不做。您要做的就是根据 tif 语句好多 更好、更易读。因此:
return t<1 ? 0 : 1;
我知道?:
运算符在某些公司中是被禁止的,我觉得这样做很糟糕。 ?:
通常与规范匹配得更好,它可以使代码更容易阅读(如果小心使用的话)...
【讨论】:
我更喜欢return !(t < 1);
或 return t >= 1;
取决于哪一个是“包罗万象”的案例。
@Bathsheba 虽然您在技术上是正确的,但由于 true==1 和 false==0,Bert 的解决方案仍然更忠实于 OP 的原件,无论如何这可能是真实代码的简化案例.
@Bathseba 原始问题显示int
返回。您依赖隐式转换,但我喜欢能够准确显示我们意图的代码。如果意图是返回一个布尔值,那么返回值应该是一个布尔值。其次,从该代码中,我推断出其意图是在“catch-all”分支上返回1
(当然事实并非如此)。因此,无需像 return !(t < 1)
那样混淆事物。以上是关于此函数是不是在所有控制路径上都有明确的返回值?的主要内容,如果未能解决你的问题,请参考以下文章