C++ c++;句柄0*(大表达式)

C++ c++;句柄0*(大表达式),c++,if-statement,switch-statement,expression,C++,If Statement,Switch Statement,Expression,关于速度,如果我需要计算一个大表达式,可以说: switch1*(large expression 1)+switch2*(large expression 2) 根据我的输入,switch1可以是0或1,也可以是switch2。什么是最快的C++,做一个if语句或写下来,上面的? ,所以,本质上你是在问“强”短路评价,你问C++除了算术表达式之外是否也做算术表达式。 证明否定是困难的,但据我所知,C++只对逻辑表达式进行短路评价,因此算术表达式没有等价性。此外,如果算术表达式以短路方式求值,

关于速度,如果我需要计算一个大表达式,可以说:

switch1*(large expression 1)+switch2*(large expression 2)

根据我的输入,
switch1
可以是
0
1
,也可以是
switch2
。什么是最快的C++,做一个if语句或写下来,上面的?

,所以,本质上你是在问“强”短路评价<强>,你问C++除了算术表达式之外是否也做算术表达式。

证明否定是困难的,但据我所知,C++只对逻辑表达式进行短路评价,因此算术表达式没有等价性。此外,如果算术表达式以短路方式求值,我可以想到很多代码会严重中断,因此我认为这是不可能的。

理论上,编译器可以生成代码,以避免计算表达式,如果它能显示出没有副作用的话。但在实践中,不太可能添加代码来检查值是否为零,因为它没有理由认为它将为零

另一方面,逻辑操作(代码> > <代码/代码>和代码> &代码>保证了C++中的短路。所以你应该使用它们

result = 0;
if(switch1) {
    result += large_expresion_1();
}
if(switch2)
    result += large_expression2();
}
但是,如果您正在优化“大表达式”,请务必检查计算它们是否真的更快,然后以无分支的方式添加它们。例如

result = ((-(uint64_t)(switch1)) & large_expression_1) + ((-(uint64_t)(switch2)) & large_expression_2);
这里记录了大量此类比特黑客:

除了基准测试之外,阅读生成的汇编语言以了解编译器实际上为您(或为您)做了什么

开关1
可以是
0
1
,开关2也可以是

如果
switch1
switch2
实际上只能有
0
1
的值,那么它们最好是布尔值而不是整数

使用布尔开关,您的语句变为:

result = (switch1 ? (large expression 1) : 0)
       + (switch2 ? (large expression 2) : 0)
在这种情况下,即使不使用表达式的结果,也会计算表达式。避免浪费计算的一个简单明了的方法是:

result = 0;
if(switch1) {
    result += large expression 1;
}
if(switch2) {
    result += large expression 2;
}
您可以通过提取方法来整理这些内容,将开关传递到这些方法中:

result = guardedLargeExpression1(switch1, otherparams1) 
       + guardedLargeExpression2(switch2, otherparams2);
。。。与

int guardedLargeExpression1(bool switch, foo params) {
    if(switch) {
        return 0;
    }
    return large expression(...);
}
你也可以做一些聪明的事情:

。。。这正接近您在Java中使用
供应商
惰性地评估代码时所做的事情


或者,因为你在C++中,而不是C,你可以做更多的OO,并且实际上使用C++的等价于<代码>供应商< /> >:

< P>如果要依赖于具体的条件。CPU,编译器,精确表达式

如果
if
成为汇编代码中的条件跳转,并且无法预测该条件,则
if
会减慢程序的速度

如果无法预测条件,并且“大表达式”实际上很简单,那么使用“乘法”可能会更快

但是,如果表达式的计算速度很慢,或者
if
可以很好地进行分支预测(或者它没有编译成条件跳转),那么我认为
if
方法会更快


总之,您应该尝试两种解决方案,并检查哪一种更快。

请提供一个解决方案,您可以在Godbolt上自己检查。如果您是大型Expression包含函数调用,编译器无法确定它们是否没有副作用,则不会对它们进行优化。如果其中任何一个开关在编译时不是常量0值,也不会对整个表达式进行优化。看起来像是过早优化。首先测量,然后优化。这取决于表达式是什么。例如,编译器能告诉我们它们没有副作用吗?
int guardedFunctionCall(bool switch, int *functionptr(foo), foo arg) {
    if(switch) {
        return 0;
    }
    return (*functionptr)(arg);
}