- ベストアンサー
インラインについて
1つ教えていただきたいことがあるのですが、本で読んだのですが普通の関数とインラインの関数は短い関数の方だとインラインの方が早いと載っていたのですが、長いほうだと普通の関数の方が早いと載っていたのですが、なぜ長いほうだと普通の関数のほうがいいのでしょうか? わかる方いらしたらよろしくお願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
> 枠組みを超えた最適化が可能とはどういうことでしょうか? 簡単な例を挙げると... inline int f(int arg) { return arg + 1; } というインライン関数があり、 a = f(5); のように呼び出すと、最適化によって、 a = 6; と展開できることを意味します。 これがインライン関数でなければ、必ず加算を実行しなければなりません。 > 例外が排出される可能性があるかどうかをコンパイラが把握できるとはどういうことなのでしょか? struct A { ~A(); }; void f(); void g() { A a; f(); } とした場合、fの呼び出しによって例外が送出されるかもしれませんから、その際にaのデストラクタを呼び出せるようにするためのコードが挿入されます。 しかし、fがインライン関数で、かつ決して例外を送出しないことがコンパイラに分かれば、そうしたコードは不要になります。
その他の回答 (5)
- jacta
- ベストアンサー率26% (845/3158)
> インラインだった場合、加算しなくてもよいと言うことでしょうか? > あれ?でも加算してますよね? > どういうときに加算しなくていいのでしょか? インライン関数の場合でも、加算しているといえばしていますが、それはコンパイル時の話であり、実行時に加算するわけではありません。
お礼
インライン関数の場合はコンパイル時の話で普通の関数は実行時に加算されるのですか。わかりました。回答ありがとうございます。
- jacta
- ベストアンサー率26% (845/3158)
処理系や文脈に相当依存します。 インライン関数が高速になる理由は以下の3点です。 1. 関数の呼出しに伴う処理(スタック操作、引数のコピー、分岐)を省ける。 2. 関数の枠組みを超えた最適化が可能になる。 3. 例外が送出される可能性があるかどうかをコンパイラが把握できる。 なお、大きなインライン関数でも、それを呼び出している箇所がプログラム全体で1箇所しかなければ、決して遅くなることはありません。
お礼
回答ありがとうございます。1つ質問なのですが、枠組みを超えた最適化が可能とはどういうことでしょうか?勉強不足ですみません。
補足
もう1つ教えていただきたいことがあるのですが、例外が排出される可能性があるかどうかをコンパイラが把握できるとはどういうことなのでしょか?本当に勉強不足ですみません。
- oldman50
- ベストアンサー率29% (8/27)
インライン関数が早いのは、関数の呼び出しや分岐によるオーバーヘッドを省くことができるからです。 たとえば、ある関数本体の処理にかかる実行時間が10で、その関数の呼び出しにかかるオーバーヘッド時間が10だとすると、インライン化して後者を省けば、全体の実行時間を半減させることができます。 しかし、関数本体の処理にかかる実行時間が1000だとすると、関数の呼び出し時のオーバーヘッドを省くことで得られる効果は、ほとんどありません。
- ymmasayan
- ベストアンサー率30% (2593/8599)
小さくても大きくてもインラインの方が実行速度は速いでしょう。 関数とのデータの受け渡しが減りますから。 ただ大きい場合その影響は全体に対して僅かでしょう。 逆にインラインにするとメモリーサイズが大きくなりますので仮想メモリーやキャッシュメモリーのヒット率が下がって実際の処理時間が延びるということはあるかも知れません。
- Interest
- ベストアンサー率31% (207/659)
インライン関数とは、コンパイル時にその関数を呼び出している部分を関数内のコードに置き換えることを行う特別な関数です。 普通の関数はコンパイルされると関数本体の実行コードが1つしか生成されません。そして、その関数が呼び出されるときはその1つしかない実行コードが呼び出されます。呼び出されるときは呼び出し元で使用しているローカル変数や引数、関数を実行した後に戻ってくる場所などをスタック領域に退避させます。 それに対してインライン関数は、コンパイルされるとその関数を呼び出している場所に、その呼び出している場所の数だけ関数本体の実行コードが作られます。インライン化された関数の実行コードはその関数を呼び出している場所にあるので、ローカル変数や引数、関数を実行した後に戻ってくる場所などをスタック領域に退避させる必要がなく、その分処理が早くなります。 しかし、呼び出される場所の数だけ、まったく同じ実行コードが何度も作られることになるのでメモリ効率が悪くなります。なので、関数が長い(=実行コードが大きい)場合はインラインにしない方が良いのです。
お礼
回答ありがとうございます。簡単に言うとインラインは関数を呼び出すたびに呼び出されるけど、普通の関数は、一度だけ呼び出されて後からまた呼び出されるときはそこからまた呼び出しをするということでしょうか?
補足
気になったので補足します。このインライン化された関数はメモリのどこの領域に行くのでしょか?
お礼
回答ありがとうございます。 後者はわかりました。 >inline int f(int arg) >{ > return arg + 1; >} >というインライン関数があり、 >a = f(5); >のように呼び出すと、最適化によって、 >a = 6; >と展開できることを意味します。 >これがインライン関数でなければ、必ず加算を実行しなければなりま >せん。 インラインだった場合、加算しなくてもよいと言うことでしょうか? あれ?でも加算してますよね? どういうときに加算しなくていいのでしょか?