我正在阅读"Optimized C++"书,并告诉那里编译器能够执行优化,例如在成功静态分派期间内联虚拟方法(当编译器能够看到不需要动态调度时) 。但是,这似乎不起作用。
The following code说明了一个由于某种原因无法完成的简单案例:
#include <iostream>
class A {
public:
__attribute__((always_inline))
virtual int f(const int x) {
if (x > 6) {
return x * 5;
} else {
return x - 5;
}
}
};
class B : public A {
public:
__attribute__((always_inline))
int f(const int x) override {
if (x > 10) {
return x * 7;
} else {
return x - 2;
}
}
};
int main() {
A *a = new B;
int n;
std::cin >> n;
return a->f(n);
}
这导致函数调用和虚拟表生成,即使使用always_inline
和-O3(但是,这种优化通常甚至在-O1级别执行)。问题是为什么编译器在这么简单的情况下这样做,然后我们甚至说要内联它:编译器能够看到不需要动态调度,因为我们知道变量的确切类型(它是{ {1}})它在整个运行时期间不会改变,可以从编译时看到。
答案 0 :(得分:4)
gcc没有堆省略,这是删除不需要的堆分配的做法。您可以在this small example:
中自行查看IP Address: a.b.c.d
这意味着在您的示例中,它无法查看int main() {
int *Value = new int(10);
return *Value;
}
并进行适当优化以删除虚拟表。请注意,gcc确实将虚拟表格为don't use heap allocations:
a
作为最后一点:clang 支持堆省略,可以看到in the assembly没有任何虚拟表。