皆さん、
「 Thinking in C++」 (Chap - インライン関数)を読んでいたときに、このステートメントに遭遇しました。
「関数のアドレスが暗黙的または明示的に取得されている場合、コンパイラはインライン化も実行できません」。
" " とはどういう意味taking address of function implicitly or explicitly
ですか?
この場合、インライン化できないのはなぜですか?
ありがとう。
皆さん、
「 Thinking in C++」 (Chap - インライン関数)を読んでいたときに、このステートメントに遭遇しました。
「関数のアドレスが暗黙的または明示的に取得されている場合、コンパイラはインライン化も実行できません」。
" " とはどういう意味taking address of function implicitly or explicitly
ですか?
この場合、インライン化できないのはなぜですか?
ありがとう。
関数のアドレスを取得するということは、それを関数ポインタに割り当てることを意味します。リンクされた例のように、これは明示的に発生する可能性があります。作成者が「暗黙的に」とは何を意味するのかわかりません-関数をパラメーターとして別の関数に渡すようなものかもしれません。
関数のアドレスを取得する場合は、最初にアドレスが必要です。インライン化は基本的に関数の呼び出しをその本体のコピーで置き換えることを意味するため、そのような変換の後、関数は存在しなくなり、アドレスがなくなります。その関数の呼び出しがあった場所には、同じコードのn 個の異なるコピーのみが存在します。したがって、関数のアドレスが何らかの方法で使用されている場合、インライン化することはできません。
実際、引用は誤解を招く可能性があります。
関数アドレスが取得された場合、ライブラリ/実行可能ファイルで関数を生成する必要があります。これは、そのアドレスによる関数の実行が、命令ポインタを関数を記述したコードのブロックにジャンプすることにあるためです。
ただし、直接呼び出された場合、コンパイラが関数を他の場所にインライン化することを妨げるものではありません。
まず、レビュー:
// Explicit:
void foo();
void (*func_ptr)() = foo;
// Implicit
struct Foo { virtual void bar() {} }; // address used in V-Table
次に、インライン化の例:
int main() {
(*func_ptr)(); // probably not inlined as the compiler can difficultly assert
// that nobody may modified it... since it's non-const.
foo(); // might be inlined
Foo f;
f.bar(); // might be inlined (the exact type of `f` is known)
// this is called, "devirtualizing"
Foo& g = accessSomeFoo();
g.bar(); // probably not inlined unless the compiler can assert
// the type returned by accessSomeFoo
// (which requires knowing its definition)
}
それが完全に真実かどうかはわかりません。ただし、関数のアドレスを取得する場合、その関数は関数のプリアンブルとクリーンアップ コードを備えたメモリ内に存在する必要があります。インライン化の際に省略されるのは、このプリアンブルとクリーンアップです。また、インライン化すると、最適化の可能性が大量に得られます。
しかし、最新のコンパイラは、関数をインライン化できる場所ならどこでもインライン化できるはずです。検討:
int compare (int a, int b)
{
return a compared to b
}
int main ()
{
a = array of ints
qsort (a, compare); // take address of compare function, thus compare function exists in
// app as a proper function
compare (value1, value2); // there's no reason why this can't be inlined
}
引用は、インライン化できないものについてより明確にする必要があると思います:
関数ポインターを介して呼び出される関数は、インライン化できません。
これは、間接呼び出し (関数ポインターを介した呼び出し) の時点でインライン化する関数をコンパイル時に決定する方法がないためです。これは、関数ポインターが指す関数を、直接呼び出された場所でインライン化できないという意味ではありません。