2016-11-10 9 views
2

私はこのようになります再帰的なC++プログラムで作られた:それは作品と私は、これは(おおよそ)それを行うための最善の方法であると仮定この種の再帰はなぜC++で動作するのですか?

using namespace std; 
#include <iostream> 

bool recursive(int num) 
{ 
    if (num == 6) 
    { 
     return false; 
    } 

    else if (num > 6) 
    { 
     return true; 
    } 

    else 
    { 
     if (recursive(num + 1)) 
     { 
      return true; 
     } 

     else 
     { 
      return false; 
     } 
    } 
} 


int main() 
{ 
    if (recursive(0)) 
    { 
     cout << "Not found!" << endl; 
    } 

    else 
    { 
     cout << "Found..." << endl; 
    } 
} 

を。

は、私の友人は、このようになりますシンプルな再帰的なプログラム作っ:ちょうど私のような

using namespace std; 
#include <iostream> 

bool recursive(int num) 
{ 
    if (num == 6) 
    { 
     return false; 
    } 

    else if (num > 6) 
    { 
     return true; 
    } 

    else 
    { 
     recursive(num + 1); 
    } 
} 


int main() 
{ 
    if (recursive(0)) 
    { 
     cout << "Not found!" << endl; 
    } 

    else 
    { 
     cout << "Found..." << endl; 
    } 
} 

彼の作品はありませんが、それは動作しますなぜ私は理解していません。私にとっては、elseブロックで何も返されないように見えるので、ブール値がどのように元の関数呼び出しに返されるかはわかりません。好奇心のうち

、私はJavaScriptで同様のプログラム製:

function recursive(index) 
{ 
    if (index == 6) 
    { 
     return true; 
    } 

    else if (index > 6) 
    { 
     return false; 
    } 

    else 
    { 
     recursive(index + 1); 
    } 
} 

if (recursive(0)) 
{ 
    console.log("found"); 
} 

else 
{ 
    console.log("not found"); 
} 

をしかし、JavaScriptのプログラムは、私は、これはC++に特異的であることを思わせるその、動作しません。

私の友人のプログラムはなぜ機能しますか?それは完全に有効か、それとも未定義の動作ですか?

+2

友人のコードが壊れています。未定義の動作。 –

+0

元のコードは25行あります。これはばかげて過度に思われる。実際には、スタックオーバーフローが完全なコードを表示しないので、リーダーはコードボックス内をスクロールダウンする必要があります。あなたは同じ機能を快適に* 7つの行に収めることができます。読み込み中でもロジックを1行に減らすことができます: 'return num <6?再帰(num + 1):num> 6; '。しかし、実際のアプリケーションでは、 'return num> 6;'を避けるべきです。 –

答えて

2

これは未定義の動作です。関数はbooleanを返すと宣言されているので、常に正しい値を返すが、必ずしも正しい値を返さない。

-Wallフラグを指定してコンパイルすると、GCCのようなコンパイラがこの種のコードを警告します。

6

なぜ機能しますか?答え:そうではありません。

else 
{ 
    recursive(num + 1); 
} 

友人のプログラムにreturnという声明がありません。

else 
{ 
    return recursive(num + 1); 
} 

void以外の値を返さないと、未定義の動作になります。

この場合、再帰呼び出しの戻り値でテストしたコンピュータでは、自動的に呼び出し元に「返されました」というメッセージが表示されます。これは、おそらく正しいレジスタに格納されていたからです。これは純粋な出来事です。あなたはそれに頼ることはできません。別のマシン、異なるコンパイラ、あるいは別の呼び出しでも、プログラムは何か他のものを返すか、クラッシュさせるか、想像できるものを実行することができます。

2

return文のない関数の終了は、C++では未定義の動作です。私ができることは、と推測されていて、関数が戻る前にスタックの最後のものであるrecursive(index + 1)への呼び出しが戻り値として取り上げられるということです。したがって、(非標準、非移植性、一般的に使用することはあまりお勧めできません)意味では、コードは暗黙的にreturn文を挿入しています。

1

確かに動作します!まあ、実際にはありません。

すべての地球上のコンパイラ(そうでないかもしれないが)警告を表示します:

打ち鳴らす:control may reach end of non-void function

GCC:control reaches end of non-void function

MVSC:not all control paths return a value

それ作業を行いますあなたの友人は十分に幸運でなかったのでこのプログラムが爆発したり、爆破したり、あなたの寝室にブラックホールを作成したりすることはありません。定義されていない動作は次のとおりです。プログラムがどのように動作するかはわかりません。

これは、標準がそれについて言いたいことです:CVボイドの戻り値の型を持つコンストラクタ、デストラクタ、または関数の終わりをオフに流れる

は、オペランドなしでリターンに相当します。それ以外の場合は、メイン(3.6.1) 以外の関数の末尾にあるの結果は、定義されていない動作になります。

関連する問題