引用とは
php でのクォートとは、同じ変数の内容に異なる名前でアクセスすることを意味します。これは c ポインターとは異なり、参照はシンボル テーブルのエイリアスです。 php では変数名と変数の内容が異なるため、同じ内容でも異なる名前が付けられることに注意してください。最も近い類似点は、unix のファイル名とファイル自体です。変数名はディレクトリ エントリであり、変数の内容はファイル自体です。参照は、unix ファイル システムのハードリンクと考えることができます。
引用は何をしますか
php の参照では、2 つの変数が同じコンテンツを指すことができます。つまり、これを行うときは次のようになります。
<?php $a =& $b; ?>
これは、$a と $b が同じ変数を指していることを意味します。
注:
ここでは $a と $b はまったく同じです。$a が $b を指しているわけではなく、$a が $b を指しているわけではなく、$a と $b が同じ場所を指しているということです。
注:
参照を持つ配列がコピーされた場合、その値は逆参照されません。配列値を関数に渡す場合も同様です。
注:
未定義の変数が参照によって割り当てられた場合、参照によって渡された場合、または参照によって返された場合、その変数は自動的に作成されます。
例 #1 未定義の変数への参照を使用する
<?php function foo(&$var) { } foo($a); // $a is "created" and assigned to null $b = array(); foo($b['b']); var_dump(array_key_exists('b', $b)); // bool(true) $c = new stdclass; foo($c->d); var_dump(property_exists($c, 'd')); // bool(true) ?>
同じ構文は、参照を返す関数と new 演算子 (php 4.0.4 以降) で使用できます。
<?php $bar =& new fooclass(); $foo =& find_var($bar); ?>
php 5 では、new は自動的に参照を返すため、ここでの =& の使用は廃止され、e_strict レベルのメッセージが生成されます。
注:
& 演算子を使用しないと、オブジェクトのコピーが作成されます。クラスで $this を使用すると、そのクラスの現在のインスタンスに適用されます。 & なしの代入はインスタンス (オブジェクトなど) をコピーし、$this はそのコピーに作用しますが、必ずしも望ましい結果になるとは限りません。パフォーマンスとメモリ消費の問題のため、通常は 1 つのインスタンスのみで作業する必要があります。
@new などの @ 演算子を使用してコンストラクター内のエラー メッセージを抑制することはできますが、&new ステートメントを使用する場合は効果がありません。これは zend エンジンの制限であり、解析エラーが発生します。
警告
関数内でグローバルに宣言された変数に参照が割り当てられている場合、その参照は関数内でのみ表示されます。これは、$globals 配列を使用することで回避できます。
例 2 関数内でグローバル変数を参照する
<?php $var1 = "example variable"; $var2 = ""; function global_references($use_globals) { global $var1, $var2; if (!$use_globals) { $var2 =& $var1; // visible only inside the function } else { $globals["var2"] =& $var1; // visible also in global context } } global_references(false); echo "var2 is set to '$var2'\n"; // var2 is set to '' global_references(true); echo "var2 is set to '$var2'\n"; // var2 is set to 'example variable' ?>
global $var; は、$var =& $globals['var']; の短縮形と考えてください。したがって、別の参照を $var に代入しても、ローカル変数への参照が変更されるだけです。
注:
参照を持つ変数に foreach ステートメントで値が割り当てられると、参照されるオブジェクトも変更されます。
例 3 引用符と foreach ステートメント
<?php $ref = 0; $row =& $ref; foreach (array(1, 2, 3) as $row) { // do something } echo $ref; // 3 - last element of the iterated array ?>
参照が行う 2 番目のことは、変数を参照によって渡すことです。これは、関数内にローカル変数を作成し、その変数が呼び出しスコープ内の同じコンテンツを参照することによって実現されます。例:
<?php function foo(&$var) { $var++; } $a=5; foo($a); ?>
$a を 6 に変更します。これは、関数 foo 内で変数 $var が $a が指すものと同じものを指しているためです。詳細な説明については、「参照による受け渡し」を参照してください。
参照が行う 3 番目のことは、参照を返すことです。
引用ではないもの
前に述べたように、参照はポインタではありません。これは、次の構成では期待される効果が得られないことを意味します。
<?php function foo(&$var) { $var =& $globals["baz"]; } foo($bar); ?>
これにより、関数の呼び出し時に foo 関数の $var 変数が $bar にバインドされますが、その後 $globals["baz"] に再バインドされます。関数 foo には変数 $bar が存在しないため ($var として表されますが、$var には変数の内容のみが含まれ、呼び出しはありません)、参照メカニズムを通じて関数呼び出しスコープ内の別の変数に $bar をバインドすることはできません。シンボル テーブルの名前と値のバインディング)。参照リターンを使用して、関数によって選択された変数を参照できます。
参照渡し
参照によって変数を関数に渡すと、関数がその引数の値を変更できるようになります。構文は次のとおりです。
<?php function foo(&$var) { $var++; } $a=5; foo($a); // $a is 6 here ?>
関数呼び出しには参照シンボルがなく、関数定義のみに参照シンボルがあることに注意してください。パラメーターを参照によって正しく渡すには、関数定義だけで十分です。最近のバージョンの php では、foo(&$a); で & を使用すると、「参照渡しによる呼び出し」が非推奨であるという警告が表示されます。
以下は参照によって渡すことができます:
foo($a) などの変数
新しいステートメント (foo(new foobar()) など)
関数から返される参照。例:
<?php function &bar() { $a = 5; return $a; } foo(bar()); ?>
詳細な説明については、リファレンスリターンを参照してください。
他の式は参照渡しできず、結果は未定義です。たとえば、次の参照渡しの例は無効です。
<?php function bar() // note the missing & { $a = 5; return $a; } foo(bar()); // 自 php 5.0.5 起导致致命错误 foo($a = 5) // 表达式,不是变量 foo(5) // 导致致命错误 ?>
これらの条件は、php 4.0.4 以降のバージョンで利用できます。
参照による返却
参照リターンは、関数を使用して参照をバインドする必要がある変数を検索する場合に使用します。パフォーマンスを向上させるために戻り参照を使用しないでください。エンジンはそれ自体を最適化するのに十分な機能を備えています。正当な技術的理由がある場合にのみ参照を返してください。参照を返すには、次の構文を使用します。
<?php class foo { public $value = 42; public function &getvalue() { return $this->value; } } $obj = new foo; $myvalue = &$obj->getvalue(); // $myvalue is a reference to $obj->value, which is 42. $obj->value = 2; echo $myvalue; // prints the new value of $obj->value, i.e. 2. ?>
この例では、getvalue 関数によって返されるオブジェクトのプロパティには、参照構文が使用されていないかのように、コピーされずに値が割り当てられます。
注: パラメーターの受け渡しとは異なり、ここでは両方の場所で & 記号を使用する必要があります。これは、通常のコピーではなく参照が返されることを示し、また、$myvalue が通常の割り当てではなく参照としてバインドされていることを示します。
注: return ($this->value); のように関数から参照を返そうとした場合、参照される変数ではなく式の結果を返そうとしているため、これは機能しません。参照変数を返すことができるのは関数からのみであり、他に方法はありません。コードが動的式または new 演算子の結果を返そうとすると、php 4.4.0 および php 5.1.0 以降では e_notice エラーが発行されます。
<?php function &test(){ static $b=0;//申明一个静态变量 $b=$b+1; echo $b; return $b; } $a=test();//这条语句会输出$b的值为1 $a=5; $a=test();//这条语句会输出$b的值为2 $a=&test();//这条语句会输出$b的值为3 $a=5; $a=test();//这条语句会输出$b的值为6 ?>
$a=test() を使用して関数を呼び出すと、関数の値が $a に割り当てられるだけです。$a を変更しても、関数内の $b には影響しません。ただし、$a=&test( ) メソッドを通じて、そのこの関数は、$b を返す $b 変数のメモリ アドレスと、$a 変数のメモリ アドレスを同じ場所にポイントすることです。これにより、この効果 ($a=&b;) と同等の効果が得られます。つまり、$ の値を変更します。 a は $b の値も変更するため、 $a=&test(); $a=5; を実行すると、$b の値は 5 になります。
逆参照
参照の設定を解除すると、変数名と変数の内容の間のバインドが解除されるだけです。これは、変数の内容が破壊されることを意味するものではありません。例:
<?php $a = 1; $b =& $a; unset($a); ?>
$b の設定は解除されず、$a のみが解除されます。
これを unix のリンク解除呼び出しと比較すると役立つかもしれません。
基準位置
多くの php 構文構造は参照メカニズムを通じて実装されるため、参照バインディングに関する上記の内容はすべてこれらの構造にも当てはまります。 pass-by-reference や return などの一部の構造については、すでに上で説明しました。参照を使用する他の構造は次のとおりです。
グローバルリファレンス
global $var を使用して変数を宣言すると、実際にはグローバル変数への参照が作成されます。つまり、これは次のことを行うのと同じです。
<?php $var =& $globals["var"]; ?>
これは、たとえば、unset $var ではグローバル変数の設定が解除されないことを意味します。
unset($a) と $a=null を使用した場合の結果は異なります。メモリ ブロックに $a のマッピングが 1 つだけある場合、unset($a) は $a=null と同等です。メモリの参照カウントは 0 になり、自動的にリサイクルされます。メモリ ブロックに $a のマッピングが 2 つある場合は、unset($a) は $a=null と同等です。 $a と $b を組み合わせた場合、 unset($a) を実行すると $a=null が発生し、 $b は変更されず、 $a=null を実行すると $a=$b=null が発生します。
理由: 変数を null に割り当てると、その変数に対応するメモリ ブロックの参照カウントが直接 0 に設定され、自動的にリサイクルされます。
$this
オブジェクト メソッドでは、$this は常に、それを呼び出すオブジェクトへの参照になります。
引用符の役割
プログラムが比較的大きく、同じオブジェクトを参照する変数が多数あり、使用後にそのオブジェクトを手動でクリアしたい場合は、個人的には "&" メソッドを使用し、次に $var=null を使用してオブジェクトをクリアすることをお勧めします。では、php5 メソッドのデフォルトを使用します。また、php5 で大きな配列を転送する場合は、メモリ領域を節約できるため、「&」メソッドを使用することをお勧めします。
もう一つ、ちょっとしたエピソードを話しましょう。php におけるアドレスのポインティング (ポインタに似た) 関数は、ユーザー自身が実装するのではなく、zend コアによって実装されます。php における参照は、「コピーオン」の原則を採用しています。 -write"、つまり、書き込み操作が発生した場合を除き、同じアドレスを指す変数またはオブジェクトはコピーされません。
分かりやすく言うと
1: 次のコードがある場合
<?ph $a="ABC"; $b=$a; ?>
実際、この時点では、$a と $b が異なるメモリを占有するのではなく、$a と $b は両方とも同じメモリ アドレスを指します。
2: 上記のコードに次のコードを追加した場合
$a="efg";
$a と $b が指すメモリ内のデータは書き換える必要があるため、zend コアはこの時点で $a のデータ コピーを $b に対して自動的に作成し、$b に対してメモリの一部を再申請することを自動的に決定します。ストレージ。