临时variables减慢我的程序?

假设我有以下的C代码:

int i = 5; int j = 10; int result = i + j; 

如果我循环了这么多次,使用int result = 5 + 10会更快吗? 我经常创build临时variables,使我的代码更具可读性,例如,如果两个variables是从一些数组中获得的,使用一些长expression式来计算索引。 在C中这是不好的性能? 其他语言呢?

现代优化编译器应该优化这些variables,例如,如果我们在godbolt中用gcc使用-std=c99 -O3标志来使用下面的例子:

 #include <stdio.h> void func() { int i = 5; int j = 10; int result = i + j; printf( "%d\n", result ) ; } 

这将导致下面的程序集:

 movl $15, %esi 

为了计算i + j ,这是常数传播的forms。

请注意,我添加了printf这样我们就有副作用,否则func会被优化到:

 func: rep ret 

这些优化在as-if规则下是允许的,这只需要编译器模拟程序的可观察行为。 这包括在C99标准的草案部分5.1.2.3 程序执行中说:

在抽象机器中,所有expression式都按照语义指定的方式进行评估。 如果一个实际的实现可以推断出它的值没有被使用,并且没有产生所需的副作用(包括由调用一个函数或者访问一个volatile对象引起的任何副作用),那么它就不需要评估一个expression式的一部分。

另请参阅: 优化C ++代码:常量折叠

这是一个优化编译器的简单任务。 它将删除所有variables并用15replaceresult

SSAforms的不断折叠几乎是最基本的优化。

你给的例子很容易编译器优化。 使用局部variables来caching从全局结构和数组中取出的值实际上可以加速代码的执行。 例如,如果您正在从for循环中的一个复杂结构中获取某些编译器无法优化的东西,并且知道该值没有更改,则局部variables可以节省相当多的时间。

您也可以使用GCC(其他编译器)来生成中间汇编代码,并查看编译器实际上在做什么。

这里讨论如何打开汇编列表: 使用GCC生成可读的程序集?

检查生成的代码并查看编译器实际在做什么可能是有益的。

虽然代码的各种微小的差异可能会扰乱编译器的行为,但性能会轻微地改善或恶化,原则上不pipe性能如何,只要程序的含义不是改变。 一个好的编译器应该以任何方式生成相同的或可比较的代码,除非为了获得尽可能接近源代码的机器代码(例如,用于debugging目的)而closures优化。

当我试图学习一个编译器的function时,你遇到了同样的问题 – 你做一个简单的程序来演示这个问题,检查编译器的汇编输出,只是意识到编译器已经优化了所有的东西你试图让它消失。 你可能会发现,main()中的一个相当复杂的操作本质上被简化为:

 push "%i" push 42 call printf ret 

你原来的问题不是“ int i = 5; int j = 10... ?会发生什么? 但是“临时variables通常会招致运行时间的损失吗?”

答案可能不是。 但是你必须看看你的特定的,非平凡的代码的汇编输出。 如果你的CPU有很多寄存器,比如ARM,那么i和j很可能在寄存器中,就像这些寄存器直接存储函数的返回值一样。 例如:

 int i = func1(); int j = func2(); int result = i + j; 

几乎肯定是完全一样的机器代码:

 int result = func1() + func2(); 

我build议你使用临时variables,如果他们让代码更容易理解和维护,而且如果你真的想要收紧循环,那么无论如何你将会看到程序集输出,以弄清楚如何精确地performance出性能可能。 但是,如果没有必要的话,不要牺牲可读性和可维护性几个纳秒。