我知道虚拟函数本质上是包含在 vtable 中的函数指针,这使得多态调用由于间接等原因而变慢。
但我想知道当调用是确定性时编译器的优化。
我所说的确定性是指以下情况:
- 该对象是一个值而不是引用,因此不可能存在多态性:
struct Foo
{
virtual void DoSomething(){....}
};
int main()
{
Foo myfoo;
myfoo.DoSemthing();
return 0;
}
- 参考的是无子类:
struct Foo
{
virtual void DoSomething();
};
struct Bar : public Foo
{
virtual void DoSomething();
};
int main()
{
Foo* a = new Foo();
a->DoSomething(); //Overhead ? a doesn't seem to be able to change nature.
Foo* b = new Bar();
b->DoSomething(); //Overhead ? It's a polymorphic call, but b's nature is deterministic.
Bar* c = new Bar();
c->DoSomething(); //Overhead ? It is NOT possible to have an other version of the method than Bar::DoSomething
return 0;
}
在第一种情况下,这不会是虚拟调用。编译器将直接发出调用Foo::DoSomething()
.
第二种情况则更为复杂。其一,它至多是一种链接时间优化,因为对于特定的翻译单元,编译器不知道还有谁可以继承该类。您遇到的另一个问题是共享库,它也可能在您的可执行文件不知道任何情况的情况下继承。
不过,一般来说,这是一种编译器优化,称为消除虚函数调用, or 去虚拟化,并且是一个活跃的研究领域。有些编译器在某种程度上做到了这一点,而另一些编译器则根本不这样做。
请参阅,在 GCC (g++) 中,-fdevirtualize
and -fdevirtualize-speculatively
。这些名字暗示了质量的保证水平。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)