【问题标题】:Member calling inline member function through function pointer, will that be inlined?成员通过函数指针调用内联成员函数,那会被内联吗?
【发布时间】:2013-02-05 17:39:34
【问题描述】:

我有一组仅算术函数,它们的调用不是在编译时确定的,而是在运行时确定的。我打算创建一个指向所有指针的数组,并通过数组索引处理它们的调用(例如,如果(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;
}

【问题讨论】:

  • 如果在编译时无法确定它们如何被内联?
  • 我的理解是:if(a>3){f2(x)}else{f1(x)}。这就像只是通过替换进行的预处理。
  • 如果内联如此重要,您可以考虑使用开关。
  • @Mysticial:总的来说你是对的,但我担心他可能会通过优化器运行他的代码,发现它是内联的,然后回来大喊它确实。上面的测试用例是trivial,编译器知道pf指的是int f(int),所以它在编译时known
  • g++ -S。只是说。

标签: c++ inline member-function-pointers


【解决方案1】:

首先,从不保证特定调用将被内联(没有使用编译器特定的扩展),因此代码中的“肯定”并不是一个肯定的选择。 p>

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

说了这么多,更重要的问题是您为什么现在担心性能?您是否有使用探查器确定的实际热点并试图改进,或者您是否只是“感觉”这将是一个问题?

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

【讨论】:

  • 我讨厌这么说,但我开始厌倦那些盲目地大喊过早优化的人。 (不管这里是否真的如此)
  • 一般来说,我也是。我尽量避免这样做。但在这种情况下,这个问题确实是求之不得。
  • 我通常同意盲目的过早优化调用,例如“
  • @Nik Bougalis 谢谢!我还没有测试过。这只是我的感觉。对于这种情况,什么时候必须在运行时决定调用哪个函数,你有什么建议?
  • 我其实并不依赖inline。如果我认为它可能很重要,我只会将其用作提示。在我绝对需要内联它的情况下(因为我知道它很重要),我会滥用宏。我什至不关心 force-inline pragma,因为我已经看到足够多的情况,编译器无法正确优化所有参数传递。 (所以结果是一堆不必要的数据复制和转换)
【解决方案2】:

如果代码在运行时决定调用哪个函数,很明显,该函数不能被内联——别无选择,只能通过指针调用它。这实际上是“编译器能否弄清楚正在发生的事情”的情况。如果您根据某些条件通过指针调用函数,那么编译器将需要了解条件如何影响使用哪个指针。如果编译器在编译代码时无法决定这一点,它必须使用函数指针。

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

但是如果发生,比如说,

在构造函数中,例如:

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

在其他一些代码中,编译器无法直接了解 x 和 y 值在构造中的含义:

*blah.*pf(); 

不能内联调用,因为编译器不知道fg 是要调用的函数。

我希望这是有道理的。

[我也想知道为什么你不能使用虚函数...]

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      现在没有这样的事情。

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

      【讨论】:

      • 这不是真的 - 在某些合法的情况下内联会有所帮助,而且通常非常有用。但它们很少。
      • "现在没有这样的事情了。" - 我不敢苟同。在某些情况下确实很重要。
      • OP 不是这样,我很确定。
      • @Mysticial 因为你更有经验,你知道得更好,我尊重它,你必须有它的经验。但我真的没有看到这样的代码,只是理论上我研究过这个。 :)
      • @Arpit 这很少见,但很重要。如果这恰好在一个关键循环中并且该函数只有少数添加,那么它会很重要 - 很多。也就是说,这是很多“如果”。但是有足够多的用户在询问之前先进行实际分析。
      猜你喜欢
      • 2023-03-02
      • 1970-01-01
      • 2010-12-01
      • 2013-10-05
      相关资源
      最近更新 更多