优化掉静态变量/通过引用传递

Optimizing away static variable / passing by reference

在这个问题 Will a static variable always use up memory? 中指出,如果地址从未被占用,则允许编译器优化静态变量,例如如下所示:

void f() {
   static int i = 3;
   printf( "%d", i );
}
  1. 如果存在一个通过引用获取其参数的函数,是否仍允许编译器优化变量,例如如
void ref( int & i ) {
    printf( "%d", i );
}
void f() {
   static int i = 3;
   g( i );
}
  1. “完美转发”的情况是否有所不同。这里的函数体是故意为空的:
template< typename T >
void fwd( T && i ) {
}
void f() {
   static int i = 3;
   fwd( i );
}
  1. 此外,是否允许编译器在以下情况下优化调用。 (函数体又是故意为空的):
void ptr( int * i ) {
}
void f() {
   static int i = 3;
   ptr( &i );
}

我的问题源于这样一个事实,即引用不是标准的指针 - 但通常作为指针实现。

除此之外,“编译器允许吗?”其实我更感兴趣的是编译器是否进行了这种优化?

that compilers are allowed to optimize away a static variable if the address is never taken

您似乎把注意力集中在了错误的答案部分。答案是:

the compiler can do anything it wants to your code so long as the observable behavior is the same

结束。你可以取地址,不要取地址,计算生命的意义,计算如何治愈癌症,唯一重要的是可观察到的效果。只要你不真正治愈癌症(或输出计算结果...),所有计算都只是空操作。

f there exists a function which takes its arguments by reference, is the compiler still allowed to optimize away the variable

是的。代码只是 putc('3').

Is the situation different for the "perfect forwarding" case

没有。代码仍然只是 putc('3').

would the compiler be allowed to optimize the call in the following case

是的。与前面的代码相反,此代码没有可观察到的效果。可以删除对 f() 的调用。

in whether compilers do this kind of optimization?

将您的代码复制到 https://godbolt.org/ 并检查汇编代码。即使没有汇编代码经验,您也会看到不同代码和编译器的差异。

选择 x86 gcc (trunk) 并记得启用优化 -O。使用 static 复制代码,然后删除 static - 代码是否更改?重复所有代码片段。

允许编译器根据“as-if”规则优化变量,这意味着允许编译器进行任何不改变程序可观察行为的优化。优化是否真正发生取决于编译器的优化器有多好,你要求什么优化级别,以及优化是否属于真正提高性能的class优化(人类不太擅长预测这一点)。

在您提供的所有示例中,as-if 规则为编译器提供了消除静态变量的自由度。

在例1中,f的定义等价于void f() { printf("%d", 3); }。由于这与您编写的 f 具有完全相同的可观察行为,因此允许编译器一个一个地替换另一个,优化变量。

在例2中,由于fwd什么都不做,所以f的定义等同于void f() {}。同样,as-if 规则允许编译器用这个空函数替换您编写的 f

就假设规则的含义而言,示例 3 与示例 2 非常相似。

如果您想查看编译器是否真的会执行这些优化,Godbolt 非常有用。例如,如果您查看 here,您会看到在 -O2,GCC 和 Clang 都将执行示例 1 中描述的优化。他们可能通过首先将 ref 内联到f.