web-dev-qa-db-ja.com

C ++は再帰の深さを制限しますか?

Pythonには、最大の再帰の深さがあります。 Pythonはコンパイラではなくインタプリタであるためだと思われます。 C++にも同じ概念がありますか?または、RAM limitのみで接続されていますか?

55
Narek

C++の制限は、スタックの最大サイズによるものです。これは通常、RAMのサイズよりもかなり小さいですが、それでもかなり大きいです。(幸いなことに、文字列contentsのような大きなものは、スタック自体に。)

スタック制限は通常、OSレベルで調整可能です。 (Unixを使用している場合は、ulimit Shellビルトインのドキュメントを参照してください。)このマシン(OSX)のデフォルトは8 MBです。

[編集]もちろん、どのくらい深く再帰できるかを考えると、スタックのサイズはそれだけでは完全には役立ちません。それを知るには、再帰関数(スタックフレームとも呼ばれます)のアクティベーションレコード(またはレコード)のサイズを計算する必要があります。 (私が知っている)それを行う最も簡単な方法は、逆アセンブラ(ほとんどのデバッガーの機能)を使用し、すべての関数の開始時と終了時にスタックポインター調整のサイズを読み出すことです。面倒です。 (たとえば、2つの呼び出しで変数へのポインターの差を計算するなど、他の方法で解決できますが、特にポータブルコードの場合はさらに厄介です。逆アセンブリから値を読み取る方がIMOが簡単です。)

47
Donal Fellows

いいえ、C++には明示的な再帰の深さはありません。最大スタックサイズ(Windowsではデフォルトで1 MB)を超えると、C++プログラムがスタックをオーバーフローさせ、実行が終了します。

22
Justin Ethier

CまたはC++標準には再帰の深さの追跡や制限はありません。実行時に、スタックが成長できる大きさによって深さが制限されます。

6
Mike DeSimone

Pythonには再帰呼び出しで 調整可能な制限 がありますが、C++はスタックサイズによって制限されます。

さらに、多くの言語またはコンパイラは、呼び出し元のスタックフレームを削除して、追加のスタックスペースが消費されないようにして、末尾再帰を最適化できます。 (末尾再帰では、呼び出し側の関数が再帰呼び出しを行った後は、再帰呼び出しの戻り値を返すだけです。)

int fact(int n, int accum=1){
  if (n==0) return accum;
  else return fact(n-1,n*accum); //tail recursion here.
}

Pythonは末尾再帰を最適化しません(ただし、 stackless Python は最適化します)。C++は末尾再帰の最適化を必要としませんが、gccは末尾再帰を最適化すると考えています。 JVMは、末尾の再帰を最適化しませんが、Scala言語は特定の一般的な文書化されたケースで行います。SchemeおよびLISP(およびおそらく他の機能言語)も末尾の再帰を最適化する必要があります。

3
Ken Bloom

C++には、スタックによって制限される最大再帰深度があります。ただし、最新のオペレーティングシステムでは、ユーザー空間のスタックがいっぱいになると動的に拡張できるため、メモリ空間とメモリの断片化のみによって再帰の深さが制限されます。

プラットフォームで利用可能なスタックのサイズが制限だと思います。私が読んだものから、それは 8K Linuxではデフォルトで8MBですが、最新のカーネルはスタックサイズを動的に調整できます。

3
Andy Shellam