3

私は最近、非仮想インターフェイス イディオム (NVI) を使用して C++ でインターフェイスを設計することにしました。主な目的は、デフォルト値を持つパラメーターを使用することです (したがって、デフォルト パラメーターが静的にバインドされているという事実によって引き起こされる問題を回避します)。

私は自分のクラスに次のようなかなり些細な宣言をしました:

class Interface{

public:
    void func(Parameter p = 0);
    virtual ~Interface();
private:
    virtual void doFunc(Parameter p)=0;

};

void Interface::func(Parameter p){ doFunc(p); }
Interface::~Interface() {}

ヘッダーに関数本体を指定すると、関数がインライン化の候補として自動的にマークされることはわかっています (ただし、定義をクラスの外に配置するとそれが妨げられるかどうかはわかりません)。また、明らかな理由で仮想関数がインライン化されていないことも知っています (実行時にどの関数が呼び出されるかわからないため、明らかに関数の本体による呼び出しを置き換えることはできません)。

次に、この場合、func()インライン化の候補としてマークされますか? これは仮想関数ではありませんが、仮想関数を呼び出します。インライン化できますか?

追加の質問: それだけの価値はありますか? 本体は 1 つのステートメントのみで構成されます。

この質問は、どこでも最適化を検索するのではなく、それについて学ぶためのものであることに注意してください。私は、この関数が数回しか呼び出されないことを知っています (まあ、今のところ、プログラムがどのように進化するかについては賢明かもしれません)。

ありがとう !

4

1 に答える 1

2

ヘッダーに関数本体を指定すると、関数がインライン化の候補として自動的にマークされることを知っています

多かれ少なかれ; ただし、クラス定義で関数本体を提供するかinline、ヘッダーにある場合は明示的に宣言することで、これを行います。それ以外の場合、関数は 1 つの定義規則の対象となり、ヘッダーを複数の翻訳単位に含めるとエラーが発生します。

これは、コンパイラが関数へのすべての呼び出しをインライン化することを強制しないことに注意してください。ヘッダーに定義を提供すると、価値があると思われる場合、ヘッダーを含む任意の翻訳単位にインライン化できます。また、一部のコンパイラは「プログラム全体の最適化」を実行でき、呼び出しサイトで定義が利用できない場合でもインライン関数を実行できます。

次に、この場合、 func() はインライン化の候補としてマークされますか? これは仮想関数ではありませんが、仮想関数を呼び出します。インライン化できますか?

はい、すべての関数はインライン化の候補です。それらが自分自身を呼び出す場合、明らかにすべての呼び出しをインライン化することはできません。また、関数がコンパイル時に不明な場合 (たとえば、仮想的に、または関数ポインターを介して呼び出す必要があるため)。この場合、関数をインライン化すると、 への直接呼び出しが へfunc()の仮想呼び出しに置き換えられdoFunc()ます。

コンパイル時に動的な型がわかっている場合、仮想呼び出しをインライン化できる場合があることに注意してください。例えば:

struct MyImplementation : Interface {/*whatever*/};
MyImplementation thing;
thing.func(); // Known to be MyImplementation, func and doFunc can be inlined

追加の質問: それだけの価値はありますか?

それは「それ」が何であるかに依存します。コンパイル時間を意味する場合、関数が短いままである限り、ごくわずかなコストでいくつかの利点が得られる可能性があります (関数が何度も呼び出される場合、おそらく重要です)。置く場所を選ぶのに時間を費やすという意味であれば、おそらくそうではありません。最も便利な場所に置くだけです。

于 2013-05-15T09:18:28.300 に答える