基类的虚拟和最终函数的成本(vtable/虚拟成本)
cost of Virtual-and-final function at base class (vtable/virtual-cost)
虚拟最终函数是否有任何虚拟/虚拟成本(final
在基类中)?
class B{
public: virtual void fFinal() final{ .... do something ..... }
public: void fCheap() { .... do something ..... }
public: virtual void fVirtual() { .... do something ..... }
};
class C : public B{
public: virtual void fVirtual() { .... do something ..... }
};
fFinal()
的成本是 =fCheap()
成本还是fVirtual()
成本?
我将使用 final+virtual 来防止人为错误("不要覆盖我")。fCheap()
不是那么安全,因为我仍然可以隐藏父级的功能。
以下链接不提供答案。
- 最终的虚拟功能有什么意义?
- 虚函数的成本是否随着继承树中类的数量而增加?
- http://en.cppreference.com/w/cpp/language/final
据我所知,任何特定的编译器如何实现虚函数机制都没有具体说明。如果类中至少有一个虚函数,即使这个虚函数被标记为 final,他们很可能会将指向 vtable 的指针放入类中。
我已经根据您的代码片段测试了一个简化的示例:
class Base {
public:
virtual void foo() final {}
};
static_assert(sizeof(Base) > 1, "No pointer to vtable");
似乎 gcc 6.3 和 clang 4.0 都添加了指向 vtable 的指针。
这意味着管理通常虚函数的规则适用于在基类中同时标记为虚拟和最终的函数。因此,Base
类的大小会增加,并且当您通过指向Base
类或从Base
派生的某个类的指针/引用调用foo
时,您需要为通过 vtable 重定向支付一些额外费用。
从纯粹的理论角度来看,不考虑编译器优化,fCheap()
确实是最快的。fFinal()
和fVirtual()
都会产生增加查找/间接寻址的成本,因为它们必须通过 vtable 调用。此外,对象大小也会因为 vtable 而增加,但这与final
无关。一旦你的类(或其基础之一)有任何虚函数,你就要支付大小成本。
进入现代优化器,即去虚拟化。增加对象大小的成本不会消失。虚拟呼叫的成本可能会增加。声明一个虚函数并立即使其成为最终函数,使编译器在编译时相对容易地证明将调用哪个函数。投注是fFinal()
调用将被解虚拟化为普通函数调用[1]。FVirtual()
是否也会发生这种情况,完全取决于呼叫现场的情况。
通常,虚拟呼叫开销很小。我不会太担心它,除非你有来自分析实际代码的有力证据,证明这是一个性能瓶颈。
更新
[1] 您赢得赌注的可能性取决于您的编译器、版本和配置。确保的唯一方法是查看从实际代码生成的程序集。我不敢在这里作一般性发言。我在编译器资源管理器中-O3
玩了一下最近的GCC和Clang。在我尝试的每个示例中fFinal()
都是内联的(当然,它们有点微不足道)。所以,很明显,两个编译器都没有问题,甚至比虚拟性更能证明。:)
- 纯虚拟类和错误未定义对 'vtable 的引用
- 虚拟继承情况下的 vtable
- 为什么虚拟继承即使不涉及虚拟功能也需要 vtable?
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 为什么虚拟类的析构函数不会自动添加到 vtable 中?
- vptr 和 vtable 在下面的虚拟相关代码中是如何工作的?
- 正在读取虚拟函数表 (vtable) 指针?
- 基类的虚拟和最终函数的成本(vtable/虚拟成本)
- 我明白为什么,但是虚拟函数/VTable 究竟如何允许通过指针访问正确的函数?
- CMake 构建错误 - 虚拟方法错误缺少 vtable
- C++ 虚拟析构函数和 vtable
- 从派生的指针中调用虚拟功能,而无需支付VTable价格
- 当一个类有一些虚拟方法时,它的所有方法都使用 vtable 吗?
- 实现纯虚拟方法后,VTable C 错误
- "vtable"链接器错误(涉及带有"=default"的虚拟析构函数) - Clang 3.1 中的潜在错误?
- 实现虚拟函数时对 vtable 的未定义引用
- c++:vtable是否包含指向非虚拟函数的指针
- 是当虚拟函数立即标记为final时生成的vtable
- 从 Objdump 实用程序检索 vptr(指向虚拟表又名 VTABLE 的指针)
- 虚拟函数的Vtable如何工作