避免使用数组分支

Avoiding branching using arrays

假设我有一个非常简单的函数,叫做 foo。 Foo 可以 return 两个值,我将使用 xy 作为任意占位符变量。

我是这样定义的:

int foo(bool expression)
{
    static const int x = ..., y = ...;

    if(expression)
        return x;
    else
        return y;
}

显然一个分支语句

我在想做类似下面的事情可以删除任何分支:

int foo(bool expression)
{
    static const int array[] = {x, y};

    return array[expression];
}

但是我不确定,通过使用 C 数组,它是否仍然会产生分支,是吗? C++ std:: 数组或向量会导致分支吗?

尝试从数组中读取是否值得,还是浪费内存和执行速度?

最后,如果 expression 包含一个逻辑表达式,例如 &&,这是否意味着它仍然会分支?

至于 condition 依靠布尔值来知道下一步要做什么,那么它肯定是分支。按理说代码本身需要等待和分支来决定访问数组中的哪个元素和return.

根据相同的概念,&& 或任何其他逻辑运算符都表示分支。

这个问题很复杂,因为在一种情况下你显示的是 bool expression,而在另一种情况下你显示的是 int condition

如果您的表达式自然计算为 int,则使用此 int 从数组中选取一项将不会涉及任何分支。如果表达式求值的最自然类型是 bool,那么您需要将其转换为 int,并且此转换可能在内部涉及分支,因此您可能不会获得任何事物。我说 "probably" 因为很大程度上取决于编译器和底层 CPU 指令集,所以除非您让编译器生成反汇编并检查反汇编,否则您不会知道。

话虽如此,我要补充一点,您消除分支的追求是徒劳的。分支本身并没有什么坏处,也不会表现得很差。诚然,最好是消除分支,但前提是这样做微不足道。如果为了消除分支,您引入了一个原本不会有的数组,那么您增加的开销可能比节省的开销多一个数量级。如果引入向量而不是数组,则引入的开销可能是数组的两倍。所以,我对此的建议是:不要担心分支。