PHPメモリ内のオブジェクトと参照の概要

公開: 2022-03-11

PHPがメモリ内の変数とオブジェクトをどのように管理するかをよりよく理解するために、PHP認定を勉強しているときに、この記事を最初に作成しました。 いろいろ調べてみると、自分の質問に対する答えを見つけるのは簡単ではないことに気づいたので、終わったら、情報を文書化して、すべてを1か所で見つけられるようにすることにしました。

この記事では、オブジェクトと変数の参照がメモリ内でどのように制御されるかについて説明します。これは、議論やさまざまな意見を生み出す可能性のある問題だからです。 熟考すべき1つの質問は、「デフォルトでは、オブジェクトは参照によって渡されるのか、それともPHPのコピーによって渡されるのか」です。 まず、PHPにない参照について説明します。 次に、それら何であるかについて説明し、最後に、PHPでガベージコレクターがどのように機能するかを調べます。

$a = new Foo();ようなステートメントを実行する場合、PHPはどのようにメモリ内にオブジェクトを作成しますか。 ? 現在、メモリは以前ほど高価ではなく、リソースも限られています。 ただし、優れたPHP開発者にとっては、アプリケーションの実行中に変数とオブジェクトが内部でどのように管理されるかを理解し、理解することが依然として重要です。

PHPメモリとPHPガベージコレクション内のオブジェクトと参照

PHPのオブジェクトと参照

多くの人が、PHPの本やオンラインで、PHPのオブジェクトはデフォルトで参照によって渡されると言います。 PHPのオブジェクトはコピーによって割り当てられると言う人もいます。 どのステートメントが正しいかを判断するには、まず、PHPで参照されているもの(および参照されていないもの)を分析する必要があります。

PHPで参照されていないものは何ですか?

PHPで参照が何であるかを知ることよりも重要なのは、それらが何でないかを知ることです。 PHPでは、参照はCスタイルのポインターではありません。 Cポインターの場合のように、参照を使用して算術演算を実行することはできません。 なんで? Cとは異なり、PHP参照は実際にはメモリアドレスではありません。これは、メモリの場所を示す数値ではないためです。 では、参照と何ですか?

PHPの参照とは何ですか

PHPでは、参照は2つの異なる変数が単一の値を読み書きできるようにする「エイリアス」です。 言い換えると、これらは、異なる名前の変数から同じ値にアクセスできるようにするメカニズムであり、同じ変数であるかのように動作します。 PHPでは、変数名と変数の内容は2つのまったく異なるものであり、「シンボルテーブル」と呼ばれるものにリンクされていることに注意してください。 したがって、参照を作成すると、シンボルテーブルにその変数のエイリアスが追加されるだけです。 次のコードがあるとします。

 $a = new Foo();

上記のステートメントが実行されると、変数$aがメモリに作成され、タイプFooのオブジェクトがメモリに作成され、変数$a 「参照」する(または関連する)ことを示すエントリがシンボルテーブルに追加されます。 、またはポイント、またはあなたがそれを呼びたいものは何でも) Fooオブジェクトですが、それ自体はそのオブジェクトへのポインタではありません。 概念的には、次の図のようなものがあります。

PHPメモリ内のオブジェクト参照

ポップクイズ:これを実行するとどうなりますか?

 $b = $a;

$b$a aの参照になるわけではありません。 $b$a aのコピーであるとも言えません。 実際に起こったことは、メモリに新しい変数$bを作成し、シンボルテーブルに新しいエントリを追加して、変数$b$a aと同じFooオブジェクトも参照していることを示しています。 したがって、視覚的には、この図に示されているものと似たものがあります。

PHPメモリ内のオブジェクト参照

さて、実行すると:

 $c = &$a;

メモリ内に3番目の変数$cを作成しますが、 $cのシンボルテーブルに新しいエントリは作成しません。 代わりに、シンボルテーブルでは、 $c$a aのエイリアスであると記録されているため、同じように動作しますが、 $c$a aへのポインターではありません。これは、ポインターへのポインターと呼ばれるものを作成するCとは異なります。 視覚化するために、この図に示されているものに似たものがあります。

変数とそのエイリアスの図

これら3つの変数のいずれかの値を変更する(つまり、新しい値を書き込む)とすぐに、PHPは、変数$bとペア$a /の内容を分離するために、メモリ内に新しいz_val構造を作成する必要があります。 $cなので、相手の値に影響を与えることなく、それぞれを個別に変更できます。 したがって、前のスクリプトに次の行を追加すると、次のようになります。

 $b = new Bar();

メモリ内では、次の図に示すような状況になります。

上記の状況のグラフィック表現

ここで、より完全な例を考えてみましょう。

 <?php class myClass { public $var; function __construct() { $this->var = 1; } function inc() { return ++$this->var; } } $a = new myClass(); // $a "references" a Foo object $b = $a; //b also references the same Foo object as a //($a) == ($b) == <id> of Foo object, but a and b are different entries in symbols table echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); $c = &$a; //$c is an alias of $a //($a, $c) == <id> of Foo object, c is an alias of a in the symbols table echo "$c = ";var_dump($c); $a = NULL; //The entry in the symbols table which links "$a" with Foo object is removed //Since that entry was removed, $c is not related to Foo anymore //Anyway, Foo still exists in memory and it is still linked by $b echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); echo "$c = ";var_dump($c); echo "$b->var: ".$b->inc(); echo "$b->var: ".$b->inc(); $b = NULL; //The entry in the symbols table which links "$b" with the Foo object is removed //There are no more entries in the symbols table linked to Foo, //So, Foo is not referenced anymore and can be deleted by the garbage collector echo "$b = ";var_dump($b);

上記のスクリプトの実装によって生成される出力は次のとおりです。

 $a = object(myClass)#1 (1) { ["var"]=> int(1) } $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = object(myClass)#1 (1) { ["var"]=> int(1) } $a = NULL $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = NULL $b->var: 2 $b->var: 3 $b = NULL

PHPガベージコレクション

最後に、バージョン5.3で導入されて以来、PHPガベージコレクションがどのように機能するかを見てみましょう。 PHPメモリ内のオブジェクトまたは変数は、シンボルテーブルにそのオブジェクトへの参照がない場合、PHPガベージコレクターによって削除されます。 つまり、PHPは、オブジェクトが作成された時点からオブジェクトの参照カウンターを維持するため、スクリプトPHPの実行中に、カウンターは、オブジェクトを「指している」変数に基づいて、その参照カウンターをインクリメントおよびデクリメントします。 参照カウントが0に達すると(つまり、そのオブジェクトを参照しているものがないため、使用されていない)、PHPはそのオブジェクトをリムーバブルとしてマークし、PHPガベージコレクターの次のパスでメモリから削除されます。 、そのスペースを再利用のために解放します。 PHPのガベージコレクションがどのように機能するかについてさらに詳しく知りたい場合は、このドキュメントをお読みください。

まとめ

PHPがメモリ内のオブジェクトと変数を処理する方法と、PHPガベージコレクターによって削除する必要のあるオブジェクトをPHPがどのように「選択」するかを少し明確にしたことを願っています。

PHPがメモリ内の変数とオブジェクトを内部で管理する方法を理解したので、ラップトップを入手して、学んだことを証明するためのコードの実験を開始します。 変数と参照を試してみてください。 また、変数の値を変更すると、それを参照している別の変数の値にどのように影響するかを試してください。 ここにあなたへの質問があります:以下のコードが実行された後の$ $a$bの値はどうなりますか?

 $a = '1'; $b = &$a; $b = "2$b";

PHPのパフォーマンス機能について詳しく知りたい場合は、ToptalerVilsonDukaの仲間によるこの投稿をチェックしてください。