1. 質問
まず例を見てみましょう:
$ar = array(1, 2, 3);
var_dump($ar);
foreach ($ar as &$v) {}
foreach ($ar as $v) {}
var_dump ($ar);
?>
出力は次のとおりです:
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
&int(2)
}
? ? ?代入演算を実行せずに配列の最後の要素の値が変化するのはなぜですか?
この問題はかなり前に発見しましたが、最初は PHP のバグだと思っていたので、foreach で参照を使用しない場合は、foreach $k => $v を使用して問題ありませんでした。そして $ar[$k] で元の配列を変更しますが、効率が若干失われます。
2. 分析
今日少し時間をかけてリファレンスの記事を読んで、やっと少し理解できました。
参照を使用して最初の foreach を実行する場合、最初は $v は $ar[0] の記憶領域を指し、foreach が終了すると、$v は $ar[0] の記憶領域を指します。 ar[2]、スペースの3つがメモリに格納されています。 次に、2 番目の foreach の実行を開始します。最初の foreach とは異なり、2 番目の foreach は参照を使用しないため、$ar の値を $v に順番に代入する代入方法であることに注意してください。 最初の要素に到達すると、 $ar[0] が $v に割り当てられます。 問題はここにあります。最初の foreach が実行されたばかりなので、$v は新しい変数ではなく、$ar[2] を指す既存の参照になります。その結果、$v に値を代入するときに、$ar[ と記述します。 $ar[2] の実際の記憶領域に 0] = 1 を設定することは、$ar[2] に値を割り当てることと同じです。 類推すると、2 回目の foreach 実行の結果は、配列の最後の要素が最後から 2 番目の要素の値になります。 詳細な回路図については、記事 2 を参照してください。
これがエラーの場合、エラーの原因は参照変数の使用にあります。 参照変数が他の変数を指している場合、参照変数の値を変更すると、当然、参照変数が指している他の変数にも影響します。 個別には誰でも理解できることですが、この foreach の例では偶然にも同じ変数が 2 回使用されており、1 回目は参照として、2 回目は通常の変数として使用されており、予想外の効果が生じています。 PHP 開発者も、この状況は言語の機能によって引き起こされており、バグではないと考えています。 実際、この問題を解決したい場合、1 つの方法は foreach で特別な処理を実行すること、もう 1 つの方法は foreach で $v のスコープを制限することです。これらの方法は両方とも、PHP および開発者の現在の言語機能と矛盾します。ただし、公式ドキュメントでは警告として説明されています。
3. 解決策
単純ですが、完璧には程遠いです。参照された foreach を使用した後、$v を設定解除すると、最初の例は次のように変更されます。
$ar = array(1, 2, 3); [0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
参考
参照と foreach:http://schlueters.de/blog/archives/141-References-and -foreach.html