c++ - 在优化阶段内联虚拟方法和静态分析

标签 c++ optimization

我正在阅读 "Optimized C++" book 并且在那里被告知编译器能够在成功的静态分派(dispatch)期间执行像内联虚拟方法这样的优化(当编译器能够看到不需要动态分派(dispatch)时)。但是,这似乎不起作用。

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) 并且在整个运行过程中不会发生变化,从编译时就可以看出来。

最佳答案

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;
// ...

作为最后的说明:clang 确实支持堆省略,可以看出in the assembly没有任何虚拟表。

关于c++ - 在优化阶段内联虚拟方法和静态分析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48450143/

相关文章:

带有 shared_ptr 的 C++ openmp

c - 可能(x)和 __builtin_expect((x),1)

c++ - 动态控制c++数据结构中的成员数量

algorithm - 为什么分支位移的 "start small"算法不是最优的?

.net - 如何在 .NET 应用程序中使用从 Win32 CryptoAPI 生成的 key blob?

c++ - 我如何将类对象写入文件?

c++ - 如何在 QThread 中运行定时器?

c++ - 数组越界元素的值——它应该在每次执行时改变还是保持不变?

string - 字符串中连续 1 的最大数目

javascript - 我怎样才能正确使用 jQuery 来修复这个 fencepost 案例?