ホームページ >バックエンド開発 >PHPチュートリアル >PHP変数の徹底解説 storage_PHPチュートリアル
1.1.1 zval 構造体
Zend は zval 構造体を使用して PHP 変数の値を保存します。構造体は次のとおりです:
struct _zval_struct {
/* 変数情報 */
zvalue_value value; /* 値 */
zend_uint refcount;
zend_uchar type; /* アクティブな型 */
zend_uchar is_ref;
};
Zend根据type值来决定访问value的哪个成员,可用值如下:
IS_NULL |
N/A |
IS_LONG |
对应value.lval |
IS_DOUBLE |
对应value.dval |
IS_STRING |
对应value.str |
IS_ARRAY |
对应value.ht |
IS_OBJECT |
对应value.obj |
IS_BOOL |
对应value.lval. |
IS_RESOURCE |
对应value.lval |
この表から 2 つの興味深いことが分かります: 1 つ目は、PHP の配列は実際には HashTable であり、これが PHP が連想配列をサポートできる理由を説明しています 2 つ目は、Resource は Long 値であり、そこに格納されるのは通常ポインタです。内部配列、または作成者だけが知っているその他のものは、ハンドルと見なすことができます。
1.1.2 参照カウント
参照カウントは、ガベージ コレクション、メモリ プール、文字列などで広く使用されています。Zend は典型的な参照カウントを実装しています。複数の PHP 変数は、参照カウント メカニズムを通じて同じ zval を共有できます。zval の残りの 2 つのメンバー is_ref と refcount は、この共有をサポートするために使用されます。
明らかに、refcount はカウントに使用され、参照が増加または減少すると、この値もそれに応じて増加または減少し、ゼロに減少すると、Zend は zval をリサイクルします。
is_ref についてはどうですか?
1.1.3 zval status
PHP には、参照変数と非参照変数の 2 種類の変数があり、それらはすべて参照カウントを使用して Zend に保存されます。非参照変数の場合、変数は相互に独立している必要があり、1 つの変数を変更する場合、変数を書き込むときに、コピーオンライト メカニズムを使用することでこの競合を解決できます。 Zend は、この変数が指す zval が複数の変数で共有されている場合、refcount が 1 の zval がそこにコピーされ、元の zval の refcount がデクリメントされます。このプロセスは「zval 分離」と呼ばれます。ただし、参照変数の場合は、非参照型の要件とは逆になります。1 つの変数を変更すると、バンドルされたすべての変数が変更される必要があります。
これら 2 つの状況にそれぞれ対処するには、現在の zval のステータスを指摘する必要があることがわかります。 is_ref は、現在 zval を指しているすべての変数が参照によって割り当てられているかどうかを指摘します。すべての参照またはなし。このとき、別の変数が変更された場合、その zval の is_ref が 0、つまり参照ではないことが判明した場合にのみ、Zend は Copy-On-Write を実行します。
1.1.4 zval 状態の切り替え
zval に対するすべての代入操作が参照または非参照である場合、1 つの is_ref で十分に対応できます。ただし、世界は常にそれほど美しいとは限りません。参照代入と非参照代入を混在させる場合、PHP はユーザーにそのような制限を課すことができません。
状況 I、次の PHP コードを見てください:
ケース II、次の PHP コードを見てください:
1.1.5 パラメータの受け渡し
PHP関数のパラメータの受け渡しは、変数の代入と同じであり、非参照の受け渡しは非参照の代入と同等であり、参照の受け渡しは参照の代入と同等であり、実行につながる場合もあります。 zval 状態切り替えの。これについては後述します。