【问题标题】:What are the adavantages and use cases of CRTP compiletime polymorphism?CRTP编译时多态有哪些优点和用例?
【发布时间】:2022-01-14 03:03:39
【问题描述】:

我看到我们可以使用 CRTP 引入某种编译时多态性,但是我想知道这怎么能比好的旧虚函数更好。最后我们必须调用static_cast<const T*>(this)->implementation();,这是一个与vtable 完全一样的间接级别。 它们有何不同?有什么优势吗?我只看到它们不能被基类破坏的缺点。在我看来,它作为一个学术示例看起来不错,但主要是常规多态性。

【问题讨论】:

  • 根据 Anger 的优化书,“我们可以通过避免使用虚函数分派机制节省的几个时钟周期不足以证明如此复杂的代码是难以理解的,因此难以维护。如果编译器能够自动进行去虚拟化,那么依靠编译器优化肯定比使用这种复杂的模板方法更方便。”
  • 考虑this clone pattern。如果没有 CRTP,您将需要在每个派生类中定义 clone() 虚函数。使用 CRTP,您只需定义一次。 CRTP 在这里不是虚拟功能的替代品。相反,这两种机制结合在一起。

标签: c++ polymorphism crtp


【解决方案1】:

原因是性能。

static_cast<const T*>(this)->implementation(); 在编译时被解析为对应的T::implementation() 重载地址:

    CALL <fixed-address>

另一方面,虚拟成员调用通常在运行时通过 vtable 中的偏移量使用间接调用来解决。在最简单的情况下,优化器可以将其转换为编译时,但没有办法可靠地做到这一点。所以通常你可以期望代码看起来像这样:

    MOV rax, <vtable-ptr>
    MOV rax, [rax+<offset>] ; Indirection via a vtable
    CALL rax

由于对目标地址的数据依赖性,这种类型的调用很可能在第一次调用时导致管道停顿,随后的调用将严重依赖分支预测器的质量。

另一方面,静态调用非常快,因为它不涉及管道停顿。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 2018-06-19
    • 2010-10-30
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多