質問: $item + 2; echo "$item\n"; } print_r($array); /* output in loop: 1 2 3 4 5 $array after loop: 1 3 4 5 6 7 */ これは最初の結論を裏付けるもので、ループ中にソース配列のコピーを処理しています。そうでなければ、ループ中に変更された値が表示されます。 しかし... manual を見ると、次のようになります。 foreachが最初に実行を開始すると、内部配列ポインタは自動的に配列の最初の要素にリセットされます。 そうです...これはforeachがソース配列の配列ポインタに依存していることを示唆しているようです。しかし、私たちはソース配列では動作していないであることを証明したばかりですよね?まあ、完全ではありません。 テストケース3 :// move the array pointer on one to make sure it doesn't affect the loop var_dump(each($array)); foreach ($array as $item) { echo "$item\n"; } var_dump(each($array)); /* output array(4) { [1]=> int(1) ["value"]=> int(1) [0]=> int(0) ["key"]=> int(0) } 1 2 3 4 5 bool(false) */ したがって、ソース配列を直接操作していないという事実にもかかわらず、ソース配列ポインターを直接操作しています。ループの終わりにポインターが配列の末尾にあるという事実は、これを示しています。これ以外は真実ではありません - もしそうなら、 テストケース1 は永久にループします。phpマニュアルにも次のように記載されています。 foreachは内部配列ポインタに依存しているため、ループ内でそれを変更すると予期しない動作を引き起こす可能性があります。 それでは、その「予期しない動作」が何であるかを調べてみましょう(技術的には、予期していた動作がわからなくなったため、動作は予期せぬものです)。 テストケース4 :foreach ($array as $key => $item) { echo "$item\n"; each($array); } /* output: 1 2 3 4 5 */ テストケース5 :foreach ($array as $key => $item) { echo "$item\n"; reset($array); } /* output: 1 2 3 4 5 */ ...そこに予想外のことは何もありません、実際にはそれは "ソースのコピー"理論を支持するようです。 質問 ここで何が起こっているの?私のc-fuはphpソースコードを見るだけで適切な結論を引き出すことができないほど私には十分ではありません。foreachは配列のcopyで動作しますが、ループの後でソース配列の配列ポインタを配列の最後に設定します。 これは正しいのでしょうか。 そうでなければ、それは本当に何をしているのでしょうか? foreach中に配列ポインタを調整する関数(each()、reset()など)を使用すると、ループの結果に影響を与える可能性がある状況はありますか?
回答: php manualで提供されているドキュメントのとおり。 繰り返しごとに、現在の要素の値が$ vと内部の要素に割り当てられます。 配列ポインタは1つ進みます(したがって、次の反復では、次の要素を見ます)。 だからあなたの最初の例のように:$array = ['foo'=>1]; foreach($array as $k=>&$v) { $array['bar']=2; echo($v); } $arrayは単一の要素しか持たないので、foreachの実行では、1は$vに割り当てられ、それ以外にポインタを移動する要素はありませんしかし、あなたの2番目の例では:$array = ['foo'=>1, 'bar'=>2]; foreach($array as $k=>&$v) { $array['baz']=3; echo($v); } $arrayには2つの要素があるので、$ arrayは0のインデックスを評価し、ポインタを1つ移動します。ループの最初の繰り返しで、参照渡しとして$array['baz']=3;を追加しました。