在一个变量中存储多个类调用总是更快

is it always faster to store multiple class calls in a variable?

本文关键字:调用 一个 变量 存储      更新时间:2023-10-16

如果您有这样的方法:

float method(myClass foo)
{
    return foo.PrivateVar() + foo.PrivateVar();
}

这样做总是更快/更好吗?:

float method(myClass foo)
{
    float temp = foo.PrivateVar();
    return temp + temp;
}

例如,我知道你不应该把foo.PrivateVar()这样的调用放在for循环中,因为当你实际上只需要使用一次值时,它会对它进行多次评估(在某些情况下。

for (int i = 0; i < foo.PrivateInt(); i++)
{
    //iterate through stuff with 'i'
}

因此,我假设将第一个例子中的代码更改为第二个例子中,但后来人们告诉我不要试图比编译器更聪明!并且它可以很好地内联调用。

我不想描述任何事情,我只想要一些简单的规则来进行良好的实践。我正在为一份工作申请写一个演示,我不想让任何人看到代码,看到一些新手的错误。

这完全取决于PrivateVar()在做什么以及它在哪里定义等。如果编译器可以访问PrivateVar()中的代码,并且可以通过调用函数来保证没有副作用,那么它可以执行CSE,这基本上是您在第二个代码示例中所做的。

对于for循环也是如此。因此,如果你想确保它只被评估一次,因为它是一个非常昂贵的函数(这也意味着即使没有副作用,也很难保证没有副作用),那么就明确地写它。

如果PrivateVar()只是一个getter,那么编写更清晰的代码——即使编译器可能不执行CSE,在99.9999%的情况下,性能差异也无关紧要。

编辑:CSE代表Common Subexpression eliminization,并完全按照它所代表的来做;)wiki页面显示了一个简单乘法的例子,但我们也可以对更大的代码结构这样做,比如函数调用。

在所有情况下,我们都必须保证只对代码进行一次评估不会改变语义,即对该代码进行CSE:

a = b++ * c + g;
d = b++ * c * d;

并将其更改为:

tmp = b++ * c;
a = tmp + g;
d = tmp * d;

显然是非法的(对于函数调用来说,这显然有点复杂,但原理是一样的)。