什么更快:检查空指针或调用空函数

What is faster: Checking for null pointer or calling empty function?

本文关键字:调用 函数 空指针 检查 什么      更新时间:2023-10-16

我正在构建一个系统,我将不得不多次调用一些命令取决于用户输入,例如

void handle(int MouseInput)
{
    switch(MouseInput)
    {
    case Move:  
        ActionMove->execute(); 
        // ...
    case BtnUp: 
        ActionBtnUp->execute(); 
        // ...
    }
}

然而,由于系统是可参数化的,我并不总是有一个actionMove命令对象(有时我在Move上什么都不做)。

哪个更快:

  • 实现空对象模式,即拥有一个具有execute函数的对象,如下所示

    execute() {}
    
  • 或者每次检查空指针:

    if (ActionBtnUp) ActionBtnUp->execute(); 
    

我要问的是什么是更大的开销,跳转到一个不做任何事情的函数的成本(也许编译器很容易优化这一点)或每次检查空指针?

注意,我现在只能测试小规模,看不到任何差异。如果是这样的话,我想知道。

在这种情况下,除非您注意到性能问题,或者您每隔几秒钟就这样做几千次,否则它可能不会对性能产生太大影响。做对你来说最有意义的事情,做最易读、最容易实现的事情。这样做在维护期间节省的时间可能比程序用于进行额外比较的总时间还要多。

为了使ActionBtnUp能够指向可能具有空execute()或可能指向可能真正做一些有用的东西的东西,您需要它指向一个基类并使execute()虚拟。

要使编译器能够优化该调用,它必须能够静态地证明指针指向的派生类型。如果它能做到这一点,它可能会告诉指针什么时候是空的,并删除检查。因此,对于编译器来说,很可能两者都不会更容易优化。

如果execute()函数还不是虚函数,那么将其更改为虚函数并添加一个新的类类型只是为了能够避免空指针检查可能是一个坏主意。当它们对行为变化有意义时,你应该使用虚函数,而不仅仅是为了微优化空指针检查。

首先优化代码的可理解性。只有当你知道你有问题的时候才去优化执行速度。根据我的经验,结构良好的代码(与良好的引用局部性松散耦合)往往也是非常快的代码。如果没有别的,编译器更容易进行优化。

在可理解性方面,null对象模式可能更好——您只在一个地方测试null。在我看来,在每次取消引用之前测试null似乎违反了"不要重复自己"。

您的ActionMove为null有意义吗?如果答案是肯定的,我相信你应该测试空指针。如果它不应该为null,就使用引用,不测试空指针