我想知道C ++编译器是否有可能在这种情况下进行优化。假设我们有一个类:
class Foo {
public:
Foo() : a(10), b(11), c(12) {};
int a;
int b;
int c;
};
我使用这个类:
int main(int argc, char *argv[]) {
Foo f;
f.a = 50;
f.b = 51;
f.c = 52;
return 0;
}
编译器是否会生成代码以将a
,b
和c
设置为各自的默认值10,11,12,然后将它们设置为50,51,52 ?或者是否允许延迟分配这些初始值,而只是稍后分配值(50,51,52),因为写入之间没有读取?基本上它必须生成代码来写这六个值,还是可以优化为三个?
如果是这样,这是否也适用于更复杂的类型(结构,类)?它叫什么,我在哪里可以阅读更多相关信息?
如果没有,为什么不呢?
答案 0 :(得分:2)
这显然取决于编译器 - 但肯定至少有一些编译器可以并且将消除死存储。实际上,根据您使用结果的方式,编译器可能会消除所有存储,无论是死还是其他。
例如,如果我们完全按照现在的方式编译您的代码,我们最终会得到这样的汇编语言:
xor eax, eax
ret
就是这样 - 因为你从不使用你存储的任何值,它完全消除了处理这些值的所有代码。剩下的就是main
返回0
这一事实,因此它只会生成main
的代码以返回零。
这可能不是你关心的一个案例,所以让我们稍微扩展一下代码,以显示更接近你可能关心的东西。
#include <iostream>
class Foo {
public:
Foo() : a(10), b(11), c(12) {};
int a;
int b;
int c;
friend std::ostream &operator<<(std::ostream &os, Foo const &f) {
return os << "(" << f.a << ", " << f.b << ", " << f.c << ")";
}
};
int main() {
Foo f;
f.a = 50;
f.b = 51;
f.c = 52;
std::cout << f << "\n";
}
在这种情况下,编译器仍然会消除所涉及的所有存储,并生成代码以直接写出我们在源代码中作为文字提供的值:
mov esi, 50
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
[和51和52重复相同的序列]。
参考:
答案 1 :(得分:1)
是的,编译器可以优化以删除初始化。此技术称为dead store优化。确定是否发生死存储是data-flow analysis的一部分。
答案 2 :(得分:-2)
首先将三个值分配给a,b和c,然后将它们更改为后面指定的值。
这是因为在c ++中,执行是逐行的。因此,首先声明对象,并在声明后立即获取构造函数指定的值。之后,a,b和c值会发生变化。
要优化它,您可以使用带有默认参数的构造函数,例如
class Foo{
public:
int a, b, c;
Foo(x = 10, y = 11, z = 12){
a = x;
b = y;
c = z;
}
};
int main(){
Foo f; //a gets 10, b gets 11, c gets 12
Foo fi(51, 52, 53); //a gets 51, b gets 52, c gets 53
}