フードの下のPHP変数


PHPの変数は、変数の型、値、このコンテナへの参照変数の量、フラグを指定するコンテナです.

構造とポインタ


構造体はクラスと非常によく似ていますが、メソッド、データ、データへのポインタ、関数へのポインタを持つことはできません.Cの構造を宣言すると、データ型を定義します.変数を定義するとき、この変数の型の代わりにこの構造体の名前を書くことができます.
my_super_struct super_struct_instance;
ポインタは変数のようですが、値はメモリにアドレスを格納します.参照変数は、ポインタの値にアクセスすることを意味します.例を見てみましょう.
// defining pointer `foo`, that will points to the variable with `int` type
int *foo;
// defining variable with `int` type
int bar = 3;

// taking reference to variable `bar` and assigning it to pointer.
// `foo` stores memory address, where `bar` stores
foo = &bar;

// with an asterisk we dereference the pointer (take the value at its address) and increment the value
(*foo)++;

// we increment the pointer itself, that means the pointer will refer at another value
foo++;

コンテナ


容器は構造物であるzval (「Zend Value」に対して短い)、任意のPHP値を表し、以下のようになります.
struct zval {
    zvalue_value value;
    zend_uchar type;
    zend_uchar is_ref;
    zend_ushort refcount;
};
我々が見ることができるように、値、タイプ、旗と参照変数の量があります.PHPzval 次の8種類をサポートします.
  • BOOL
  • LONG (符号付き整数型)
  • DOUBLE (浮動小数点数を格納するために使用)
  • STRING
  • ARRAY
  • OBJECT
  • RESOURCE
  • NULL
  • zvalue_valueunion . unionは、異なる型の複数のメンバー宣言を持つことができる特別な型ですが、1つだけが使用されます.以下のように定義します:
    typedef union _zvalue_value {
        long lval; // integer
        double dval; // float
        struct {
            char *val;
            int len;
        } str; // string
        HashTable *ht; // array
        zend_object obj; // object
    } zvalue_value;
    
    その結果、この型の変数を作成するとき、それは、コンテントの最も重い要素を占有するのと同じくらい正確にメモリを受け取ります.

    なぜ、我々はこのすべてを必要としますか


    まず、なぜ私たちがrefcountを必要と理解しましょう.これは非常に簡単です.別の変数の変数値に代入すると、zval , and refcount インクリメント.

    これらの変数の値を変更すると、PHPはrefcount 1より大きい場合、これをコピーしますzval , 変更を行い、変数は既に新しいzval . 次のようになります.
    PHP
    フードの下で
    $foo = "baz";
    $bar = $foo;
    
    bar,foo: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 0
        refcount: 2
    }
    
    $bar .= "q";
    
    foo: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 0
        refcount: 1
    }
    bar: {
        type: string,
        value:
            str:
                val: "bazq"
                len: 4
        is_ref: 0
        refcount: 1
    }
    
    この技術は、「コピー・オン・ライト」と呼ばれ、メモリ消費をかなり良くすることができる.またrefcount ガベージコレクターに必要です.zval これはrefcount = 0 .
    そして、何が参照で起こりますか?And is_ref 動いているかこれは非常に簡単です:変数からリファレンスを作成すると、isCount refフラグは1になり、このzvalの上記の最適化は適用されません.
    PHP
    フードの下で
    $foo = "baz";
    $bar = $foo;
    bar,foo: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 0
        refcount: 2
    }
    
    $baz = &$foo;
    baz,foo: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 1
        refcount: 2
    }
    bar: { // variable `bar` was allocated to a separate `zval`
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 0
        refcount: 1
    }
    
    $qwe = $foo;
    baz,foo: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 1
        refcount: 2
    }
    bar: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 0
        refcount: 1
    }
    // this variable was also allocated to a separate `zval`
    qwe: {
        type: string,
        value:
            str:
                val: "baz"
                len: 3
        is_ref: 0
        refcount: 1
    }
    

    Interesting in reading more about PHP? Follow this link to find more articles 😉