先日、この一見非常に単純な質問に出くわしました $array1 を参照せずに $array2 の値を変更するにはどうすればよいですか? しかし、調べれば調べるほど、これが実際に意図したとおりに機能しているように見えたのは奇妙に思えました。この後、次の出力から生成されるオペコードを調べ始めました。
$array1 = array(2, 10);
$x = &$array1[1];
$array2 = $array1;
$array2[1] = 22;
echo $array1[1]; // Outputs 22
array2 は array1 のコピーのみであるべきであり、1 つの配列に発生したことは他の配列の内容に影響を与えるべきではないため、これは私にはおかしいようです。もちろん、2行目をコメントアウトすると、最終行は予想どおり 10 をエコーアウトします。
さらに調べてみると、Vulcan Logic Dumper を使用して PHP が生成するオペコードを示すクールなサイトがありました。上記のコードによって生成されたオペコードを次に示します。
Finding entry points
Branch analysis from position: 0
Return found
filename: /in/qO86H
function name: (null)
number of ops: 11
compiled vars: !0 = $array1, !1 = $x, !2 = $array2
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > INIT_ARRAY ~0 2
1 ADD_ARRAY_ELEMENT ~0 10
2 ASSIGN !0, ~0
4 3 FETCH_DIM_W $2 !0, 1
4 ASSIGN_REF !1, $2
5 5 ASSIGN !2, !0
6 6 ASSIGN_DIM !2, 1
7 OP_DATA 22, $6
8 8 FETCH_DIM_R $7 !0, 1
9 ECHO $7
10 > RETURN 1
これらのオペコードは、 http://php.net/manual/en/internals2.opcodes.phpにはあまり文書化されていませんが、英語ではオペコードが次のことを行っていると思います。一言で言えば…誰よりも私に向いているかもしれません。
- 行 3: 配列を最初の値で初期化し、$array1 に割り当てる前に 10 を追加します。
- 行 4: 書き込み専用を取得しますか? 値を配列から取得し、参照によって $x に割り当てます。
- 5 行目: $array1 を $array2 に設定します。
- 行 6: 1 の配列インデックスを取得します。$6 が返されることはありませんが、od_data はそれを 22 に設定していると推測しています。OD_DATA にはドキュメントがまったくなく、私が見たどこにもオペコードとしてリストされていません。
- 8 行目: $array1 のインデックス 1 から読み取り専用の値を取得し、それをエコーします。
オペコードを調べても、どこが間違っているのかわかりません。オペコードに関するドキュメントが不足していると感じています。また、オペコードを使用した経験がないため、これがどこで間違っているのかを理解できていない可能性があります。
編集1:
最初のコメントで Mike が指摘したように、配列の参照ステータスはコピー時に保持されます。ここでは、 http://php.net/manual/en/language.types.array.php#104064にリンクしている配列の記事の場所とともにドキュメントを見ることができます。この面白いことは警告とは見なされません。これが本当なら、私にとって驚くべきことは、あなたが期待するように、このコードの参照ステータスが保持されていないことです.
$array1 = array(2, 10);
$x = &$array1;
$array2 = $array1;
$array2[1] = 22;
echo $array1[1]; // Output is 10
したがって、これは参照によって単一の要素を割り当てようとした場合にのみ発生し、この機能がさらに混乱するようです。
php が個別に割り当てられた配列インデックスのステータスのみを保持するのはなぜですか?
編集2:
今日、HHVM を使用していくつかのテストを行いましたが、HHVM はコードの最初のスニップを処理します。私は PHP が大好きですが、HHVM は Zend Engine よりも優れているように見えます。