【问题标题】:Is virtual dispatch used if class type is known?如果类类型已知,是否使用虚拟调度?
【发布时间】:2015-09-08 15:56:45
【问题描述】:

假设我们有一个基类A 至少有一个虚方法。假设我们有另一个类 B 派生自 A 并且可能会或可能不会覆盖此虚拟方法。

最后,假设您创建了一个具有本地范围的B 类的对象,并调用此虚拟方法。

从 C++ 文档中我们知道,如果这个虚方法是内联的,则将使用内联版本,因为类类型是已知的,这不是指针或引用,而是类本身。

在这种情况下会使用虚拟调度还是会被绕过?这适用于普通(非内联)方法吗?

我对 gcc/clang 感兴趣。

【问题讨论】:

  • C++ 没有 vtable 的概念,这是特定于编译器实现的。
  • 谢谢。使用 gcc 标签更新的问题
  • 如果你在栈上创建B,那么编译器就知道它是什么类型了,所以它不需要经过vtable。如果您要传递对象,请注意切片问题。

标签: c++ gcc clang vtable


【解决方案1】:

由于堆栈和 vtable 都是实现细节,因此最好将其表述为:

如果对象的(真实、运行时)类型是静态已知的,编译器能否使用静态而不是虚拟调度?

答案是:是的。只要编译器确定将使用哪个版本的虚方法,它就可以发出一个常规的静态分派函数调用。

请注意,您可能在某些地方期望编译器知道对象的运行时类型并误会 - 特别是在构造函数内部。

如果您想知道特定编译器是否确实为某些特定代码(在特定优化级别)发出这种特定优化,只需检查汇编输出即可。即使您不确定调用的两个版本应该是什么样子,您也可以将输出与一个简单且完全限定的调用 (b.B::foo() vs b.foo()) 进行比较。在这种情况下,我希望 gcc 和 clang 能做一个合理的工作,但检查起来很容易。

【讨论】:

  • 检查时,在 -O0 和 -O2 处都这样做。去虚拟化在技术上是一种优化。
猜你喜欢
  • 2011-09-07
  • 1970-01-01
  • 2013-03-08
  • 2015-12-15
  • 2020-10-21
  • 2015-01-08
  • 1970-01-01
  • 2014-09-28
  • 2021-08-22
相关资源
最近更新 更多