テキストブックで、インライン関数に再帰、go to、ループなどを含めることができないと読みました。なぜですか? そうしても構文エラーが発生するとは思いません。
5 に答える
あなたの教科書は間違っています。
inline
まず、「関数を次のように宣言する」という概念と実際の「関数呼び出しをインライン化する」という概念の違いを理解することが重要です。前者は関数自体に適用され、後者は各呼び出しに個別に適用されます。
現在、インライン関数には絶対に何でも含めることができます。また、関数へのほとんどすべての直接呼び出しをインライン化できます。制限は一切ありません。
ループやローカルの goto を含むコードをインライン化しても、明らかに問題はありません。したがって、インライン関数に「ループまたは goto を含めることはできません」と本に記載されている場合、特定の (そしておそらく非常に古い) コンパイラの癖を参照しているに違いありません。コンパイラは、実装固有の理由でそのような関数をインライン化できませんでした。
再帰は別の話です。明らかに、コンパイル時に再帰の深さが不明な場合、ネストされたすべての再帰呼び出しを完全にインライン化することはできません。それでも、再帰を特定の制限された深さまで「アンラップ」することは可能です。つまり、コンパイラは、たとえば 5 レベルの深さの再帰呼び出しをインライン化してから、本物の (インライン化されていない) 再帰呼び出しに進むことができます。これは、「サイクル アンローリング」として知られる最適化手法と大差ありません。したがって、再帰関数もインライン化できます。一部のコンパイラでは、再帰関数のインライン展開の深さを制御することさえできます。
このコードは完全に有効です:
class Test
{
public:
inline void sayHello(int i);
};
void Test::sayHello(int i)
{
std::cout << "Hello "<< i << std::endl;
if (i>0)
sayHello(i-1);
}
int main(int argc, char** argv) {
Test t;
t.sayHello(10);
}
.. 期待どおりに再帰します。
(GCC 4.6.3)
この場合、インライン化はコンパイラのヒントにすぎないため、関数はインライン化されません。要件ではありません。
上記のコメントの提案者として、ここでより完全な答えを見つけることができます: Can a recursive function be inline?
マイクが言ったように、言語定義には関数に対するそのような制限はありませんinline
。ときどき表示されるのは、再帰、ループなど、コンパイラがインライン展開しない言語構造が使用されているため、関数がインライン展開されていないというコンパイラの警告です。これは、関数がインライン展開されていないことを示しているだけです。 、したがって、必要な最適化が得られませんでした。コードは有効で、結果の実行可能ファイルは正しく機能します。
インライン関数でループや再帰などを使用できますが、適切なプログラミングの実践では使用しません。ループで記述された命令の実行ごとに、CPU で管理する必要があるためです。メモリ内の余分なスペースを消費する可能性があります。