17

配列を宣言するとしましょう:

$data = array( 'foo' => 'bar' );

次に、それ自体への参照を新しい要素として追加します。

$data['baz'] = &$data;

の内容をダンプすると、次の$dataようになります。

Array
(
[foo] => bar
[baz] => Array
    (
        [foo] => bar
        [baz] => Array
         *RECURSION*
    )

)

これで、配列の内容をダンプできます。$data['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']結果は上記とまったく同じになります。これは、配列が要素としてそれ自体へのポインターを持っているためです。

私が知りたいのは、phpが配列を、使用時に呼び出すのとまったく同じポインターを持つ1つのデータセットとして処理する$dataか、またはまったく異なることを行うかどうかです。

また、PHP の内容を返すときにメモリ不足になることはあり$data{['baz']*n}ますか?

4

1 に答える 1

11

PHP の内部では、すべてがZVALと呼ばれるバリアントコンテナー内に格納されます。は ZVAL で表され、内部の各キーと各値は ZVAL などです。$data$data

したがって、最初の割り当ての後、PHP から 3 つの ZVAL が作成されました。

   /-------------------\      /-------------------\   
   | ZVAL #1           |  /==>| ZVAL #2           |   
   |   type: array     |  |   |   type: string    |   
   |   data: [         |  |   |   data: "foo"     |
   |      {            |  |   \-------------------/
   |          key: =======/                         /-------------------\
   |          val: ================================>| ZVAL #3           |
   |      }            |                            |   type: string    |
   |   ]               |                            |   data:  "bar"    |
   \-------------------/                            \-------------------/

注: 配列項目の内部表現は、上記のものとは対応していません。不必要な詳細で答えに負担をかけたくありませんでした。ZVAL の表現も同じ理由で簡略化して示されています。PHP の内部構造について詳しく知りたい場合は、ソースおよび/またはこのをお読みください。

"foo"およびが配列のキー/値のペアとして使用されているという事実は"bar"、それらの ZVAL を見て判断することができないことがわかります。それらが配列によって参照されていることを知る必要があります。

割り当ての後、$data['baz'] = &$data循環参照が発生します。ZVAL #1 内のどこかに、ZVAL #1 へのポインターがあります。

   /-------------------\      /-------------------\   
   | ZVAL #1           |  /==>| ZVAL #2           |   
/=>|   type: array     |  |   |   type: string    |   
|  |   data: [         |  |   |   data: "foo"     |
|  |      {            |  |   \-------------------/
|  |          key: =======/                         /-------------------\
|  |          val: ================================>| ZVAL #3           |
|  |      },           |                            |   type: string    |
|  |      {            |                            |   data: "bar"     |
|  |          key: =========================\       \-------------------/
|  |          val: =========\               |       
|  |      }            |    |               |       /-------------------\
|  |   ]               |    |               \======>| ZVAL #4           |
|  \-------------------/    |                       |   type: string    |
|                           |                       |   data: "baz"     |
\===========================/                       \-------------------/

では、PHP はどのように解決するの$data['baz']['baz']でしょうか。$dataが ZVAL#1 で表されていることを認識しており、配列構文でインデックスを作成しようとしていることがわかります。ZVAL を見て、それが配列であることを確認し、キー"baz"を持つアイテムを見つけて、それを表す ZVAL を取得します。あなたは何を知っていますか?再びZVAL#1です。これで の解決は終了$data['baz']です。

$data['baz']次のステップで、配列としてインデックスを作成しようとしていることがわかります。それが$data['baz']ZVAL#1 によって表されることを認識しているため、同じことが再び発生するなどです。

上記のプロセスでは、中間結果を保存する必要がないことに注意してください (最初のステップと 2 番目のステップは完全に独立しています)。つまり、配列アクセスを解決しようとするときに、PHP 仮想マシンがリソース制限に達することはありません。

于 2013-10-22T13:15:38.143 に答える