今日、Java では、再帰関数の一部である場合、配列とプリミティブの動作が異なることを指摘しました。たとえば、整数 (N) を配列 (denom[]) で指定された異なる金種の硬貨で表現できる方法の数を見つけるための次の再帰コードを考えてみましょう。
public static void printAll(int ind, int[] denom,int N,int[] vals){
if(N==0){
System.out.println(Arrays.toString(vals));
return;
}
if(ind == (denom.length))return;
int currdenom = denom[ind];
for(int i=0;i<=(N/currdenom);i++){
vals[ind] = i;
printAll(ind+1,denom,N-i*currdenom,vals);
}
}
関数がそれ自体を呼び出すと、変数 vars (各金種の実際の数値を格納する) と N が次の呼び出しに渡されるため、それらは同じままであることは明らかです。ただし、再帰が巻き戻されると (1 つの関数呼び出しが完了し、プログラムが最後の呼び出しに戻る)、興味深いものになります。ここで、N の値は、巻き戻されたばかりの呼び出しが行われたときの値にすぐにリセットされます。この関数はその動作に依存しているため、これは幸いです。ただし、vals[] 配列はそれとは異なる動作をします。アンワインド呼び出しから行われたすべての変更が保持されます。これは、次にループに入ったときに更新されるため、ここでは問題になりません。しかし、Java でプリミティブと配列の動作が異なる理由に興味がありました。また、この動作は C で期待できますか? C++ と C# も?N がスタンドアロンのプリミティブ引数ではなく、何らかの配列の一部である場合、この関数は機能しないことに注意してください。