我试图评估在写这个表达式时是否有性能影响
bool func() {
if (expr1 || expr2 ... || exprN)
return 1;
return 0;
}
作为
bool func() {
if (expr1)
return 1;
if (expr2)
return 1;
...
if (exprN)
return 1;
return 0;
}
我尝试做后者的原因只是为了提高可读性/可维护性(例如,后者可以用辅助宏编写,从而更容易添加/删除expr
s这种情况下大约有50个表达式)。
类似的情况是写作
bool func() {
if (expr1 && expr2 && ... && exprN) {
return 1;
}
return 0;
}
作为
bool func() {
if (!expr1) {
return 0;
}
if (!expr2) {
return 0;
}
...
if (!exprN) {
return 0;
}
return 1;
}
在这种情况下是否有性能损失?如果是这样,编译器优化尝试优化它?我有兴趣知道gcc
是否这样做。
(为了给出一些上下文,表达式本身就是函数,让我们说我们想确定是否所有或至少一个返回true。函数接受不同类型的参数)
答案 0 :(得分:2)
您的两个版本功能相同。
在C / C ++(以及许多其他语言)中,逻辑运算符||
和&&
执行"short-circuit" evaluation。它们从左到右评估子表达式,一旦结果已知就停止。在||
的情况下,这意味着它一获得真(非零)结果就会停止(因为true || anything
为真);在&&
的情况下,它一旦得到假(零)结果就停止(因为false && anything
为假)。
如果您在if
机构中执行任何其他操作,而不仅仅是从函数返回,那么对于每个表达式都是重复的。但是,因为只要其中一个表达式为真,您就会从函数返回,所以您永远不会测试任何剩余的表达式。所以它正在做同样的短路。
如果您确实在身体中有某些动作,则可以使用else if
而不是if
来获得相同类型的短路。但是,这会违反DRY原则。但如果它是宏的输出而不是原始源代码,那么这不会是一个重要的问题(虽然它可能会增加生成的代码的大小 - 如果采取极端,这可能会影响内存性能)
答案 1 :(得分:1)
您当前的代码
bool func() {
if (expr1 || expr2 ... || exprN)
return 1;
return 0;
}
涉及无数逻辑表达式的可以写成可能更清晰的&维护
auto func()
-> bool
{
return false
|| expr1
|| expr2 ...
|| exprN;
}
这使编译器有了最佳的优化机会,因为它提供了有关所需效果的完整信息。
相比之下,编译器必须分析一系列单独的if
语句,以确定它们是否实现了OR链。
一如既往对微观表现有疑问, MEASURE 。
答案 2 :(得分:0)
生成C和C ++代码到其程序集等效项。 因此,我认为生成的代码不应该有所不同,除非你有多个输出函数或跳转语句(包括Return,就像你在第二个例子中所做的那样)。 所以我认为除非你在改进的可读性代码中有太多的跳跃,否则不会有性能损失。