【问题标题】:What is the overhead of dynamic_cast<>dynamic_cast<> 的开销是多少
【发布时间】:2021-07-26 07:37:38
【问题描述】:

所以我用 C++ 编程已经有一段时间了,有人告诉我,使用动态转换将抽象类指针的指针转换为不同的具体类指针是不好的做法。

Shape* GeneralShape = new Triangle(...);
Triangle* triPtr = dynamic_cast<Triangle*>(GeneralShape);

Shape 是一个抽象类,而 Triangle 继承自它。

当您继承的一个类与抽象类所包含的通用函数有点不同并且需要更多的通用函数时,使用动态转换似乎是一种访问成员函数的便捷方式。我只是想知道运行时多态有什么不好或开销是多少?

【问题讨论】:

  • "运行时多态的开销是多少?" - dynamic_cast 必须扫描对象的 RTTI 以发现 Triangle 是否真的继承自 @987654325 @ 以及如何将 Shape* 指针调整为 Triangle* 指针。这在运行时需要时间和精力。
  • 这不像是概念上的东西那样的开销。您可能会牺牲速度(也可能不会)以换取更容易理解和维护的代码。旁注:当你发现自己让继承类有点不同时,你可能会反对Liskov Substitution Principle,并且没有你想象的那么好的继承候选者。

标签: c++ inheritance polymorphism abstract-class run-time-polymorphism


【解决方案1】:

虚拟调度的“运行时开销”相当低,除非在紧密循环中,否则可能无关紧要:

  • 查找正确的函数
  • 使用地址间接调用函数
  • 如果 CPU 分支预测器错误预测调用,则管道停止

dynamic_cast 增加了一些额外的开销:

  • 遍历类型继承的运行时表示以获得对象指针的正确调整因子(或失败)。如果继承图不深,这仍然相当快。

更大的代价是在编译时错失优化机会。特别是在 C++ 中,使用编译时多态性(模板)通常会导致大量内联、循环消除、预计算等。当运行时多态性发挥作用时,这些优化通常是不可能的。

有趣的是,dynamic_cast 对编译时优化的障碍较小,因为编译器只需要考虑两种情况——转换成功和转换失败,程序员将其编写为两个单独的代码路径,都需要优化。相比之下,使用虚拟调用的“推荐”运行时多态性方法更难优化,因为可能的类型集是开放式的。

为了便于维护(如@user4581301 cmets),虚拟调用通常优于dynamic_cast(或标记和切换),其次是性能考虑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2017-09-27
    • 1970-01-01
    • 2011-05-17
    • 2012-01-05
    • 2016-04-15
    • 2013-05-06
    相关资源
    最近更新 更多