代码之家  ›  专栏  ›  技术社区  ›  VP.

优化阶段的内联虚拟方法和静态分析

  •  1
  • VP.  · 技术社区  · 8 年前

    我正在读 "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水平下进行)。问题是为什么编译器在如此简单的情况下会这样做,然后我们甚至会说将其内联:编译器能够看到不需要动态调度,因为我们知道变量的确切类型(它是 B )而且它在整个运行时都不会改变,可以从编译时看到。

    1 回复  |  直到 8 年前
        1
  •  4
  •   Rakete1111    8 年前

    gcc没有堆省略,这是一种删除不需要的堆分配的实践。你可以在 this small example :

    int main() {
      int *Value = new int(10);
      return *Value;
    }
    

    这意味着在您的示例中,它无法透视 a 并适当优化以删除虚拟表。请注意,gcc确实省略了虚拟表 don't use heap allocations :

    // ...
    B b;
    A &a = b;
    // ...
    

    最后一点:叮当声 支持堆省略,如图所示 in the assembly 没有任何虚拟表。