打破条件表达

时间:2015-01-27 02:09:38

标签: c++ c gcc

我试图评估在写这个表达式时是否有性能影响

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。函数接受不同类型的参数)

3 个答案:

答案 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,就像你在第二个例子中所做的那样)。 所以我认为除非你在改进的可读性代码中有太多的跳跃,否则不会有性能损失。