成员通过函数指针调用内联成员函数,就会被内联

Member calling inline member function through function pointer, will that be inlined?

本文关键字:成员 函数 调用 指针      更新时间:2023-10-16

我有一组仅算术函数,它们的调用不是在编译时确定的,而是在运行时确定的。我打算创建一个指向所有指针的数组,并通过数组索引处理对它们的调用(例如,如果(a>3)调用第三个)。

这些函数将在循环中被大量重复调用,因此为了提高性能,它们必须内联。

我的问题是,这样一个通过内联成员函数指针的调用最终会被内联吗?

谢谢!

class foo{
    private:
    int f(int x){return x;}
    int (foo::*pf)(int);
    public:
    foo(){
        pf=&foo::f;
        (*this.*pf)(3); //will this call be inlined?
        f(3);           //this call is surely inlined
    }
};
int main(){
    foo f;
    return 0;
}

首先,永远不能保证特定的调用会被内联(除了使用编译器特定的扩展),所以代码中的"肯定"不是一个确定的选择。

您的示例中的函数指针调用可以内联(因为编译器可以使用静态分析判断调用的是什么函数),但该示例是人为的,我怀疑您的代码是否那么简单。

话虽如此,但更重要的问题是,你为什么现在担心表现?您是否使用您正在尝试改进的探查器确定了实际的热点,或者您只是"感觉"这将是一个问题?

专注于编写干净、可理解和可维护的代码,然后编写并调试后,您可以专注于通过微优化对其进行性能调整。

如果代码在运行时决定调用哪个函数,显然,该函数不能内联-别无选择,只能通过指针调用它。这实际上是一个"编译器能弄清楚发生了什么吗"的问题。在通过基于某些条件的指针调用函数的情况下,编译器需要了解这些条件如何影响所使用的指针。如果编译器不能在编译代码时决定这一点,那么它必须使用函数指针。

因此,在示例代码中,编译器可以(如果选择这样做的话)内联foo和图f

但在的情况下

在构造函数中,例如:

if (x > y) pf = foo::f(); else pf = foo::g();

在其他一些代码中,编译器不直接知道x&y值正在构建中:

*blah.*pf(); 

调用不能内联,因为编译器不知道要调用的函数是f还是g

我希望这是有道理的。

[我还想知道为什么不能使用虚拟函数…]

在一般情况下,不会。在您的特定情况下,编译器可以看到指向成员的指针是如何获得的,并且编译器可以看到所有内容。

"这些函数将在循环中被大量重复调用,因此为了提高性能,它们必须内联。"

现在根本没有这种事。

对于您的内联ans:该调用将内联或不依赖于编译器。