优化掉静态变量/通过引用传递
Optimizing away static variable / passing by reference
在这个问题 Will a static variable always use up memory? 中指出,如果地址从未被占用,则允许编译器优化静态变量,例如如下所示:
void f() {
static int i = 3;
printf( "%d", i );
}
- 如果存在一个通过引用获取其参数的函数,是否仍允许编译器优化变量,例如如
void ref( int & i ) {
printf( "%d", i );
}
void f() {
static int i = 3;
g( i );
}
- “完美转发”的情况是否有所不同。这里的函数体是故意为空的:
template< typename T >
void fwd( T && i ) {
}
void f() {
static int i = 3;
fwd( i );
}
- 此外,是否允许编译器在以下情况下优化调用。 (函数体又是故意为空的):
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
.
在这个问题 Will a static variable always use up memory? 中指出,如果地址从未被占用,则允许编译器优化静态变量,例如如下所示:
void f() {
static int i = 3;
printf( "%d", i );
}
- 如果存在一个通过引用获取其参数的函数,是否仍允许编译器优化变量,例如如
void ref( int & i ) {
printf( "%d", i );
}
void f() {
static int i = 3;
g( i );
}
- “完美转发”的情况是否有所不同。这里的函数体是故意为空的:
template< typename T >
void fwd( T && i ) {
}
void f() {
static int i = 3;
fwd( i );
}
- 此外,是否允许编译器在以下情况下优化调用。 (函数体又是故意为空的):
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
.