プログラムに関数があり、コードのどこかに、その関数が関数ポインターを介して呼び出されるとします。コンパイラがたまたまその関数をインライン化した場合、またはその関数に関数ポインタが割り当てられていることをコンパイラが認識してインライン化を回避した場合はどうなりますか。
4 に答える
関数へのポインターが取得されると、コンパイラーは関数の行外の本体を生成します。他の呼び出しサイトで関数をインライン化することは引き続き可能です。
マークされた関数はinline
、それを参照するすべての TU で利用可能な定義を持たなければならず、これらの定義は同一でなければならないことに注意してください。つまり、一部の呼び出しサイトで関数をインライン化し、他のサイトではインライン化しないことは完全に安全です。
なるほど、きっと効きます。インライン化がそれをどのように防ぐかわかりません。関数を直接呼び出すコードがいくつかあり、そこにインライン化されている可能性があり、通常の関数と同様に、関数ポインターを介して呼び出すコードがいくつかあります。
関数ポインターを使用することでインライン化を防ぐ必要があるという理由はありません。インライン化はケースバイケースで行われ、通常の関数本体と一緒に存在できます。したがって、関数をある場所でインライン化し、別の場所で呼び出すことができます。
したがって、コンパイラは、関数ポインターの呼び出し可能な関数を生成できる場所をインライン化します。
コンパイラは「関数の他の呼び出し」をインライン化するだけでなく、実際に使用されている関数を十分に理解していれば、関数ポインタを介してインライン呼び出しを行うこともできます。
typedef void (*funcptr)();
void somefunc()
{
... do stuff here ...
}
void indirection(funcptr *f)
{
f();
}
void call_with_ptr()
{
funcptr f = somefunc();
for(int i = 0; i < 100; i++)
{
indirection(f);
}
}
これに似たコードがあり、間接参照をインライン化し、関数ポインターを使用せずにsomefunc()を直接呼び出しました。
ただし、もちろん、これは、コンパイラーがコードから呼び出される関数を判別できることを前提としています。これはこの場合は明らかですが、実行時の決定が含まれる場合は、そうではない場合があります。