0

私は一連の算術専用関数を持っていますが、その呼び出しはコンパイル時ではなく実行時に決定されます。それらすべてへのポインターの配列を作成し、配列インデックスを介してそれらの呼び出しを処理するつもりでした (たとえば、(a>3) が 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;
}
4

4 に答える 4

3

まず第一に、特定の呼び出しがインライン化されるという保証はありません(コンパイラ固有の拡張機能を使用する場合を除く) ため、コード内の「確実に」は確実ではありません。

あなたの例の関数ポインター呼び出しはインライン化できます (コンパイラーは静的分析を使用して呼び出されている関数を認識できるため) が、その例は不自然であり、コードがそれほど単純であるとは思えません。

そうは言っても、より重要な質問は、なぜ今パフォーマンスについて心配しているのかということです。改善しようとしているプロファイラーを使用して特定された実際のホットスポットがありますか、それとも単にこれが問題になると「感じている」だけですか?

クリーンで理解しやすく保守可能なコードを書くことに集中し、コードを書いてデバッグし は、マイクロ最適化によるパフォーマンスの調整に集中できます。

于 2013-02-05T17:46:50.183 に答える
1

コードが実行時に呼び出す関数を決定する場合、明らかに、関数をインライン化することはできません。ポインターを介して呼び出す以外に選択肢はありません。それは実際には、「何が起こっているかどうかをコンパイラが把握できるか」というケースです。いくつかの条件に基づいてポインターを介して関数を呼び出す場合、コンパイラーは、条件が使用されるポインターにどのように影響するかを理解する必要があります。コードをコンパイルする時点でコンパイラがこれを決定できない場合、コンパイラは関数ポインタを使用する必要があります。

したがって、サンプル コードでは、コンパイラは (そうすることを選択した場合)fooと figureの両方をインライン化できfます。

しかし、たとえば、

コンストラクターでは、たとえば次のようになります。

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

他のコードでは、コンパイラは x と y の値がどのように構成されているかを直接認識していません。

*blah.*pf(); 

呼び出しをインライン化することはできません。これは、コンパイラが呼び出す関数であるかどうfかがわからないためです。g

これが理にかなっていることを願っています。

【仮想関数が使えない理由も気になる…】

于 2013-02-05T18:33:41.517 に答える
0

「これらの関数はループ内で頻繁に繰り返し呼び出されるため、パフォーマンスのためにインライン化する必要があります。」

今の時代、そのようなことはありません。

インライン ans の場合:その呼び出しはインライン化されるか、コンパイラに依存しません。

于 2013-02-05T17:49:34.373 に答える
0

一般的なケースでは、いいえ、そうではありません。コンパイラーがメンバーへのポインターがどのように取得され、すべてがコンパイラーに表示されるかを確認する特定のケースでは、それが可能です。

于 2013-02-05T17:45:48.440 に答える