【问题标题】:virtual destructor performance [duplicate]虚拟析构函数性能
【发布时间】:2012-12-20 15:28:58
【问题描述】:

可能重复:
Virtual functions and performance - C++

我有一些课:

class I
{
public:
  virtual void foo() = 0;
protected:
  virtual ~I(){}
};

该类不提供删除实例的接口,所以将析构函数设为protected是很合乎逻辑的解决方案。因此,没有必要将析构函数设为虚拟。但我有虚拟化的代码。

这看起来不像是一个大错误,但它对代码性能有显着影响吗? 当我们创建虚函数时,我们向虚函数表中添加了一条记录,当我们进行虚调用时,我们在该表中进行搜索。所以这意味着查找时间增加了。我对吗?

【问题讨论】:

  • vcall 的开销确实很小。它不像一个大表查找——它只是另一个指针取消引用。因此,在这里或那里只删除它的一个实例,vcall 的开销将可以忽略不计。如果它发生在一个紧密的循环中,那么您可能会关心 - 但此时唯一知道的方法就是对其进行基准测试。
  • 如果调用是在多态上下文中,你只做一次表查找。听起来好像不是这里的情况,所以应该没有间接性。

标签: c++ performance


【解决方案1】:

即使这是一个问题(它不是),不,它不会增加时间。查找实际上并不是运行时查找任何东西——vftable 有多大并不重要。它确切地知道在表格内跳转到哪里。

所以 - 调用 virtual 方法有一些成本 - 实际查找没有成本。

【讨论】:

    【解决方案2】:

    通常,在使用多态类时,您应该始终将析构函数声明为virtual。否则你会遇到以下经典问题:

    Base *derived = new Derived();
    delete derived;
    

    与代码中存在潜在问题相比,对性能的担忧肯定是无关紧要的。今天你不需要删除对象,也许明天你会,如果你忘记了这一点,你最终会产生一些微妙的错误。

    virtual 调用的成本是存在的,但除非每秒调用数百万个虚拟方法,否则您永远不必担心。

    虽然在 vtable 中查找方法不是运行时操作,但它是编译时操作。编译后,您的代码已经知道 vtable 的哪个索引被指定的方法占用。花费的时间是间接从vtable中获取函数地址。

    【讨论】:

      【解决方案3】:

      很好的答案。虚函数调用的成本就像猿猴身上的一根头发。

      但是,一般而言,析构函数可能很慢,无论是否是虚拟的,因为它确实很容易使您的数据和类结构过于复杂,因此当您删除某些内容时,它可以运行 27 米的软件,而您没有甚至意识到它在做。

      【讨论】:

        猜你喜欢
        • 2013-07-06
        • 2011-08-12
        • 2012-04-13
        • 2012-04-18
        • 2017-03-16
        • 2014-11-04
        • 1970-01-01
        • 2016-01-22
        • 2017-05-31
        相关资源
        最近更新 更多