声明一个虚函数可以减慢它的速度;备择方案?

时间:2014-05-12 13:44:25

标签: c++

我有一个名为WorkerA的类,它适用于一种图像格式(我们只称它为A,它相当不标准)。该课程运作良好:

class WorkerA
{
public:
    void Setup()
    {
          //some stuff specific to format A
     }

     void MainTask()
     {
          //some algorithm that calls GetPixel() a lot
     }
    //...

protected:     
     int GetPixel(int x, int y)
     {
          int value;
          //value = ... (gets pixel value in format A)
          return value;
     }

     unsigned char * pBitmapA;
     //...
};

现在我需要另一个适用于图像格式B的类。MainTask和其他一些函数与WorkerA相同,但剩下的函数需要不同的实现。不确定这种情况下的最佳做法,我将以下内容混为一谈:

class WorkerB : public WorkerA
{
public:
    void Setup()
    {
          //some stuff specific to format B
    }
    //... (other functions. MainTask not re-implemented.)

protected:     
     virtual int GetPixel(int x, int y)
     {
          int value;
          //value = ... (gets pixel value in format B)
          return value;
     }

     unsigned char ** pBitmapB;     //different format than pBitmapA
};

到目前为止,我还将WorkerA::GetPixel设为虚拟,以便在调用WorkerB::MainTask时获得正确的多态行为。但是,这一次更改导致WorkerA::MainTask比以前运行时间长50% - 这是我真正需要避免的。

我的问题是:我应该如何重新排列这两个类,以便尽可能少的重复代码,而没有速度惩罚?如果有必要,我可以完全重写WorkerA和WorkerB(虽然我最好能保留WorkerA的现有界面),但我不能改变图像格式。

2 个答案:

答案 0 :(得分:5)

通常,为每个像素调用的任何成像代码都会变慢。如果可以,重构代码,使其适用于更大的块,一次可能是栅格线。

如果您可以确定在编译时使用哪个类而不是运行时,则可以使用Curiously Recurring Template Pattern (CRTP)来消除虚拟调用的开销。

答案 1 :(得分:0)

不是一个真正的答案,但这里有一些值得关注的主题。

  1. 从性能的角度来看,GetPixel()是一个出了名的坏事。认真考虑使用不需要严重依赖于此的算法。如果确实需要,可以将其转换为内联或模板或宏。

  2. 您确定基准吗?虚函数调用的固有开销是几个机器指令,通常不会造成如此严重的影响。你确定这里没有其他东西吗?

  3. 你真的需要虚拟吗?继承是许多问题的解决方案,并非所有问题都需要虚函数和动态绑定。也许你可以重新组织你的代码以使用静态继承或模板,至少在你需要的很多部分,并完全避免对GetPixel()的虚拟调用。

  4. 如果您有更多信息,请相应地修改您的问题。