【问题标题】:is it always faster to store multiple class calls in a variable?将多个类调用存储在一个变量中总是更快吗?
【发布时间】:2012-01-05 22:31:01
【问题描述】:

如果你有这样的方法:

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'
}

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

我不想描述任何东西,我只是想要一些简单的规则,以便在这方面进行良好的实践。我正在为一个工作申请编写一个演示,我不希望任何人看到代码并看到一些菜鸟错误。

【问题讨论】:

  • 我们可以假设这个函数没有副作用吗?否则这是一个毫无意义的比较。
  • 无论哪种方式,你都会让人们抱怨;没有灵丹妙药。例如 建议您不要将 for 循环优化作为一种​​习惯,因为这意味着您可能会在值的情况下搞砸并编写错误的代码PrivateInt() 返回的值在循环过程中发生变化。 IMO,“正确”的事情是学习如何编写正确、可读的代码,并分别学习如何以及何时进行优化。

标签: c++ visual-studio optimization coding-style


【解决方案1】:

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

对于您的 for 循环,情况完全相同。因此,如果您想确保它只被评估一次,因为它是一个非常昂贵的函数(这也意味着即使没有任何副作用,也很难保证没有副作用)明确地编写它。

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

编辑:CSE 代表 Common Subexpression eliminiation 并且完全符合它的含义;) wiki 页面显示了一个简单乘法的示例,但我们也可以对较大的代码结构执行此操作,例如函数调用.

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

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

并将其更改为:

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

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

【讨论】:

  • @Cicada,你知道 87% 的统计数据都是虚构的吗?
  • 所以基本上做第二个,除非它只是一个简单的吸气剂?那么您是否还说可以将getter放入for循环中?没有人会因此评判我吗?因为一个 stack-overflower 将我的代码的特定方面称为“禁止”。
  • 您能否为我们这些不以编写编译器为生的人定义什么是 CSE?
  • @SirYakalot,互联网上的人们抱怨很多事情。这里的大多数人都同意先说清楚,然后只在出现问题时才担心性能。见xkcd.com/386
  • @SirYakalot 我希望你能带走的是:编写尽可能清晰的代码,除非你知道它是应用程序的性能关键部分,在这种情况下你可能想要明确地这样做。就个人而言,我已经经常编写您的 for 循环示例,并且已经看到许多优秀的编码人员使用它。我真的不会担心。上面的 99.99% 可能有点夸张,但您编写的绝大多数代码对性能并不重要,但人们仍然需要阅读和理解它。
猜你喜欢
  • 1970-01-01
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 2021-02-28
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多