PHP 参照 (つまり、変数、関数、オブジェクトなどの前に & 記号を追加すること)、PHP での参照とは、異なる名前が同じ変数の内容にアクセスすることを意味します。 C言語のポインタとは異なります。 C言語におけるポインタは変数の内容とメモリ上に格納されているアドレスを格納します。
1. 変数リファレンス
PHP リファレンスでは、2 つの変数を使用して同じコンテンツを指すことができます
コードをコピーします コードは次のとおりです:
$a="ABC";
$ b =& $a;
echo $a;// ここに出力: ABC
echo $b;// ここに出力: ABC
$b="EFG";
echo $a;// ここでの $a の値は次のようになりますEFG なので EFG
を出力 echo $b;//EFG
を出力?>
2. 参照による関数転送 (アドレスによる呼び出し)
アドレスによる呼び出しについては詳しく説明しません
コードをコピーします コードは次のとおりです。 ?php
function test(&$a) {
$a=$a+100;
}
$b=1;
echo $b;//出力 1
test($b); // ここで $b が渡されますto 関数は、実際には $b の変数の内容が配置されているメモリ アドレスです。関数内の $a の値を変更することで、$b の値を変更できます。 b;//出力 101
?>
ここでtest(1);を使用するとエラーが発生するので注意してください。
注: 上記の「test($b);」では $b の前にアンパサンドを追加しないでください。ただし、関数「call_user_func_array」では、渡されたパラメータを参照したい場合は、次のようにアンパサンドが必要です。次のコード内:
コードをコピー
コードは次のとおりです:function a(&$b){ $b++;
}
$c=0;
call_user_func_array( 'a',array(&$c)) ;
echo $c;
//出力 1
?>
3. 関数リファレンス return
まずコードを見てください
コードをコピーします
コードは次のとおりです: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(); で得られるものは、実際には関数の参照戻りではありません。理由としては、これは PHP の規定です。
PHPでは、 $a=&test(); メソッドが関数の参照戻りであると規定されています。 参照戻りとは何かについては、PHPのマニュアルには次のように書かれています。に縛られるべきです。) これはでたらめです 長い間理解できませんでした
上記の例を使用して説明すると、
$a=test() を使用して関数を呼び出すと、関数の値が $a に代入されるだけであり、$a への変更は関数内の $b
には影響せず、呼び出し時に $ が渡されます。 a=&test() を使用する関数の場合、その関数は、$b を返す $b 変数のメモリ アドレスと、$a 変数のメモリ アドレスを同じ場所にポイントすることであり、これにより、この効果と同等の効果が得られます ($a =&$b;) したがって、$a の値を変更すると、$b の値も変更されます。したがって、
$a=&test();
$a=5;
を実行すると、$b の値は 5 になります
。
ここで静的変数を使用するのは、関数の参照戻りを誰もが理解できるようにするためです。実際、関数の参照戻りは主にオブジェクトで使用されます
。
公式の PHP サンプルを添付します:
コードをコピーします
コードは次のとおりです:
これは、ポインターを使用してクラス内の変数にアクセスする方法です。class talker{ private $data = 'Hi'; public function & get(){
Return $this->data;
}
public function out(){
echo $this->data;
}
}
$ aa = 新しい話者 ();
$d = &$aa->get();
$aa->out();
$d = '方法';
$aa->out();
$d = ' Are';
$aa->out();
$d = 'You';
$aa->out();
?>
//出力は「HiHowAreYou」です
4. オブジェクトリファレンス
コードをコピーします コードは次のとおりです:
参照 b;
echo $b->abc;//ABC をここに出力
echo $c-> ;abc;//ここに ABC を出力します
$b->gt;abc="DEF";
echo $c->gt;abc ;//ここに DEF を出力します
?>
上記のコードはPHP5での実行エフェクトです
PHP5では、オブジェクトの代入は参照処理です。上記の列の $b=new a; $c=$b; は、実際には $b=new a; $c=&$b; と同等です PHP5 のデフォルトでは、オブジェクトを参照によって呼び出すことになります。オブジェクトのコピーを作成し、元のオブジェクトへの変更がコピーに影響しないことを望みます。この目的のために、PHP5 は __clone と呼ばれる特別なメソッドを定義します。
PHP 5 では、new は自動的に参照を返すため、ここでの =& の使用は廃止され、E_STRICT レベルのメッセージが生成されます。
php4 では、オブジェクトの割り当てはコピープロセスです。
例: $b=new a、new a は匿名のオブジェクトインスタンスを生成し、このときの $b はこの匿名オブジェクトのコピーです。同様に、$c=$b も $b の内容のコピーです。したがって、php4 では、メモリ領域を節約するために、$b=new a を参照モード、つまり $b=& new a に変更するのが一般的です。
これが別の公式の例です:
php5 では、「オブジェクト参照」機能を実現するために他に何も追加する必要はありません:
コードをコピーします
コードは次のとおりです:
class foo{
protected $name;
function __construct($str){
$this->name = $str;
}
__toString(){
return 「私の名前は「」です。 $this->name .'" そして私は "' . __CLASS__ '" に住んでいます。 。 "n";
}
function setName($str){
$this->name = $str;
}
}
class MasterOne{
protected $foo;
__ construct($f){
$this- >foo = $f;
}
function __toString(){
return 'マスター: ' 。 __クラス__ 。 ' | foo: ' . $this->foo 。 "n";
}
function setFooName($str){
$this->foo->setName( $str );
}
}
class MasterTwo{
protected $foo;
関数 __construct($f) {
$this->foo = $f;
}
function __toString(){
return 'Master: ' 。 __クラス__ 。 ' | foo: ' . $this->foo 。 "n";
}
function setFooName($str){
$this->foo->setName( $str );
}
}
$bar = new foo('bar');
print(" n");
print("$bar の作成と $barn の印刷のみ");
print( $bar );
print("n");
print("現在 $baz は $bar を参照し $bar の印刷を行っていますそして $bazn");
$baz =& $bar;
print( $bar );
print("n");
print("MasterOne と Two を作成し、両方のコンストラクターに $bar を渡しますn");
$m1 = 新しい MasterOne( $bar );
$m2 = 新しい MasterTwo( $bar );
print( $m1 );
print( $m2 );
print("n");
print("現在変更中です$bar の値と $bar と $bazn の出力");
$bar->setName('baz');
print( $bar );
print( $baz );
print("n");
print("MasterOne and Twonを再度印刷中");
print ( $m1 );
print( $m2 );
print("n");
print("MasterTwo の foo 名を変更して、もう一度 MasterOne と Twon を印刷します");
$m2->setFooName( 'MasterTwo's Foo' );
print( $m1 );
print( $m2 );
print("$bar と $bazn も印刷します");
print( $bar );
print( $baz );
?>
输出:
复制代码代码如下:
$barとprinting $barのみを作成しました
私の名前は「bar」で、私は「foo」に住んでいます。
今、$bazは$barとprintingを参照しています$bar と $baz
私の名前は「bar」で、「foo」に住んでいます。
今、MasterOne と Two を作成し、両方のコンストラクターに $bar を渡しています
マスター: MasterOne | foo: 私の名前は「bar」で、「foo」に住んでいます。
マスター: MasterTwo | foo: 私の名前は「bar」で、「foo」に住んでいます。
$bar の値を変更して、$bar と $baz を出力します
私の名前は「baz」で、「foo」に住んでいます。
私の名前は " baz" と私は "foo" に住んでいます。
MasterOne と Two を再度印刷中です
マスター: MasterOne | foo: 私の名前は「baz」、「foo」に住んでいます。
マスター: MasterTwo | foo: 私の名前は「baz」で、「foo」に住んでいます。
MasterTwo の foo 名を変更して、もう一度 MasterOne と Two を印刷します
Master: MasterOne | foo: 私の名前は「MasterTwo's Foo」、「foo」に住んでいます。
Master: MasterTwo | foo: 私の名前は "MasterTwo's Foo" で、"foo" に住んでいます。
$bar と $baz も印刷します
私の名前は "MasterTwo's Foo" で、"foo" に住んでいます。
私の名前は "MasterTwo's Foo" で、私は「foo」に住んでいます
前の例の分析:
コードをコピーします コードは次のとおりです:
$bar = new foo('bar');
$m1 = new MasterOne( $bar );
$m2 = 新しい MasterTwo( $ bar );
インスタンス オブジェクト $m1 および $m2 の $bar は、インスタンス $bar への参照であり、コピーではありません。これは、php5 のオブジェクト参照、つまり、$m1 または $m2 内の任意の参照の機能です。 $ bar の操作は、外部オブジェクト インスタンス $bar の関連値に影響します。
2. 外部オブジェクトインスタンス $bar への変更は、$m1 と $m2 内の $bar の参照値にも影響します。
php4 では、上記のようにオブジェクト インスタンスを使用して別のオブジェクトのプロパティを参照する場合、同等のコード (つまり、参照呼び出し) は次のようになります:
コードをコピーします コードは次のとおりです。次のように:
class foo{ var $bar;
function setBar(&$newBar){
$this->bar =& newBar;
}
}
5. 参照の役割 プログラムが比較的大きく、同じオブジェクトを参照する変数が多数あり、オブジェクトを使用した後に手動でクリアしたい場合は、個人的には「&」メソッドを使用することをお勧めします。それ以外の場合は、php5 のデフォルトのメソッドを使用します。また、php5 で大きな配列を転送する場合は、メモリ領域を節約できるため、「&」メソッドを使用することをお勧めします。 。
6. 参照解除
参照の設定を解除すると、変数名と変数の内容の間のバインドが解除されます。これは、変数の内容が破壊されることを意味するものではありません。例:
コードをコピー コードは次のとおりです:
$a = 1;
$b =& $a;
unset ($a);
?>
は $b の設定を解除せず、$a のみを解除します。
7.グローバル参照
global $varで変数を宣言すると、実際にはグローバル変数への参照が確立されます。これは、
$var =& $GLOBALS["var"];
?> を実行するのと同じです。これは、たとえば、unset $var はグローバル変数の設定を解除しないことを意味します。
関数内でグローバルとして宣言された変数に参照が割り当てられている場合、その参照は関数内でのみ表示されます。これは、$GLOBALS 配列を使用することで回避できます。
関数内でグローバル変数を参照する例
コードをコピーします
コードは次のとおりです:$var1 = "変数例";
$var2 = "";
function global_references($use_globals)
{
global $var1 , $var2;
if (!$use_globals) {
$var2 =& $var1; // 関数内でのみ表示されます
} else {
$GLOBALS["var2"] =& $var1; context
}
}
global_references(false);
echo "var2 is set to '$var2'n"; // var2 は ''
global_references(true);
echo "var2 は '$var2' に設定されますn"; / /var2 は 'サンプル変数' に設定されます
?>
global $var; は $var =& $GLOBALS['var']; の略称と考えてください。したがって、別の参照を $var に代入しても、ローカル変数への参照が変更されるだけです。
8.$this
オブジェクトのメソッドでは、$this は常にそれを呼び出すオブジェクトへの参照になります。
//ここでまたちょっとしたエピソードです
PHP におけるアドレスのポインティング (ポインタに似た) 関数は、ユーザー自身によって実装されるのではなく、PHP の参照は「コピーオン」の原則を採用しています。 write"、つまり、書き込み操作が発生しない限り、同じアドレスを指す変数またはオブジェクトはコピーされません。
わかりやすく言うと
1: 次のコードがあるとします
[code]
$a="ABC";
$b=&$a;
?>
実際、この時点では、$a と $b が異なるメモリを占有するのではなく、同じメモリ アドレスを指します2: 上記のコードに次のコードを追加すると
コードをコピーします
コードは次のとおりです: $a="EFG";
?>
$a と $b が指すメモリ内のデータを書き換える必要があるため、この時点で Zend コアは $a の $b 用のデータ コピーを自動的に決定して自動的に生成し、
PHP のリファレンス (つまり、変数、関数、オブジェクトなどの前にアンパサンドを追加する) は高度なトピックであり、大きな影響を与える PHP リファレンスを正しく理解することが重要です。パフォーマンスに影響を与える可能性があり、誤解がプログラム エラーにつながる可能性があります。
多くの人は、PHP の参照が C のポインターと同じであると誤解しています。実際には、それらは異なり、大きく異なります。配列転送プロセス中に明示的に宣言する必要のない C 言語のポインターを除き、他のポイントは * を使用して定義する必要があります。ただし、PHP のアドレスへのポインター (ポインターと同様) 関数は、はい、PHP の参照は「コピーオンライト」の原則を採用しています。つまり、書き込み操作が発生しない限り、同じアドレスを指す変数やオブジェクトはコピーされません。 、次のコードのようになります:
コードをコピー コードは次のとおりです:
$a = array('a','c'...'n');
$b = $a;
ここでのみプログラムが実行される場合、$a と $b は同じですが、C とは異なり、$a と $b は異なるメモリ空間を占有しますが、同じメモリを指します。これが php と c の違いです。 $b が $ を指すことを意味するために $b=&$a と書く必要はありません。 a のメモリについては、zend がすでに参照を実装しており、zend はそれをいつ処理すべきかを判断するのに非常に賢明です。この方法で扱うべきでない場合と、この方法で扱うべきではない場合。
後で次のコードを書き続ける場合は、関数を追加し、パラメーターを参照渡しして、配列のサイズを出力します。
コードをコピーします コードは次のとおりです:
function printArray(&$arr) //参照渡し
{
print(count($arr));
}
printArray($a);
上記のコードでは、$a 配列を参照によって printArray() 関数に渡します。zend エンジンは、printArray() によって $a が変更される可能性があると判断します。 $b 用の $a のデータ コピーが自動的に作成され、ストレージ用にメモリが再適用されます。これが、前述した「コピーオンライト」の概念です。
上記のコードを次のように変更すると:
コードをコピー コードは次のとおりです:
function printArray($arr) //値の転送
{
print(count($arr));
}
printArray($a);
上記のコードは $a 値を printArray() に直接渡します。現時点では参照転送がないため、コピーオンライトは行われません。
上記の 2 行のコードの実行効率をテストできます。たとえば、ループを 1000 回外に追加して、実行にかかる時間を確認します。その結果、参照を不適切に使用するとパフォーマンスが低下することがわかります。 30%以上。
自己理解: 値渡しの場合は関数内のパラメータとは無関係でローカル変数の役割に相当しますが、アドレス(参照)渡しの場合は関数内のパラメータに関係します、これはグローバル変数の役割と同等です。パフォーマンスの観点からは、上記の分析を見るだけで十分です。 .
http://www.bkjia.com/PHPjc/743931.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/743931.html技術記事 PHP リファレンス (つまり、変数、関数の前に lt;? $a="ABC"; $b = echo $a;//ここに出力: ABC echo $b;//ここに出力: ABC $b) を追加します。オブジェクトなど ="EFG"; echo $a;// ここでの $a の値は...
声明:この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。