我想知道是否有可能的优化,即使对象的类型是具有虚拟方法的类,编译器也不需要将 vptr 分配给实例化对象。

例如考虑:

#include <iostream>
struct FooBase
{
  virtual void bar()=0;
};

struct FooDerived : public FooBase
{
  virtual void bar() { std::cout << "FooDerived::bar()\n"; }
};

int main()
{
   FooBase* pFoo = new FooDerived();
   pFoo->bar();

  return 0;
}

在这个例子中,编译器肯定知道编译时 pFoo 的类型,所以它不需要为 pFoo 使用 vptr,对吗?是否存在更有趣的情况,编译器可以避免使用 vptr?

有帮助吗?

解决方案

建立在 安德鲁斯坦的回答, ,因为我想你也想知道什么时候可以避免所谓的“虚拟函数的运行时开销”。(开销是存在的,但是 微小的, ,并且很少值得担心。)

真的很难避免 空间 vtable 指针的值,但指针本身可以被忽略,包括在您的示例中。因为 富福的初始化在该范围内,编译器知道 pFoo->bar 一定是指 FooDerived::酒吧, ,并且不需要检查vtable。还有几种缓存技术可以避免多次 vtable 查找,从简单到复杂。

其他提示

即使你表现出的情况下,我怀疑任何编译器会你有什么建议。

正在使用所有在一个文件中一个非常简单的程序。

设想一下,你在foo.h中和Foo.cpp中有FooBase和FooDerived和main.cpp的主。当编译Foo.cpp中,如何编译器知道,在整个程序就没有必要为一个VTBL。它没有见过的main.cpp。

在最终判定只能在链接时间作出的,当它是太晚和复杂修改的对象文件,找到所有为sizeof(FooDerived)等

的呼叫

即使是最现代化的,全球范围内优化的编译器仍然坚持“独立翻译”的原则。根据这一原则,每个翻译单元独立编制,没有关于可能在整个最后的程序中存在任何其他的翻译单元的任何知识。

在声明具有外部链接的类,该类可以在其他的翻译单元使用。编译器无法了解您的类可能在与其他翻译单元使用的想法。因此,它必须假设,在一般需要一个类可能的每个实例的虚拟表指针在施工时刻正确初始化。

在您的示例智能编译器可能弄清楚,动态类型*pFoo对象是FooDerived。这将允许编译器优化代码:生成响应于FooDerived::bar表达pFoo->bar()函数的直接调用(不使用虚拟表)。但尽管如此,编译器通常仍然必须正确初始化虚拟表指针中的每个FooDerived对象。

这是可能的编译器将切出的虚拟函数调用的间接开销时它知道它的确切类的方法将被调用。这是一种形式的结果的点到分析该优化编译器做的。他们跟踪数据流指针的变量,和任何地方指针只能指向一种类型的目标,它可以产生用于准确该类型的呼叫,静态实现虚拟调用语义(即在编译时)。

,它仍然需要产生某种虚函数表的支持独立的汇编;

由于许多人说过,除非编译器正在执行的整个程序/链接时优化(在4.5 GCC的收益也越来越受欢迎)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top