回答:
PHPのドキュメントによれば、これは値によるものです。
デフォルトでは、関数の引数は値で渡されます(関数内の引数の値が変更されても、関数の外では変更されません)。関数が引数を変更できるようにするには、引数を参照で渡す必要があります。
関数への引数が常に参照によって渡されるようにするには、関数定義の引数名の前にアンパサンド(&)を付加します。
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
$str = add_some_extra($str);
参照を使用していない場合と同じですよね?次に、その真の付加価値は何ですか?
$str
、nullが割り当てられていることに注意してください。
PHPでは、デフォルトでオブジェクトは参照コピーとして新しいオブジェクトに渡されます。
この例を参照してください.............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
これを見てください..............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
これを見てください..............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
ご理解いただければ幸いです。
$y
それは必要ありません-それが中にあるfunction changeValue
ことを必要とするものは何もないclass Y
ので、2つの無関係な概念を絡み合わせます。function changeValue
すぐ上の外側のスコープに移動し$x = new X();
ます。への参照をすべて削除します$y
。これで、最初の2つの例では$ xがそのままになり、3番目の例では内容がに変更されていることが簡単にわかりnew Y()
ます。あなたがダンプかどうかを確認するために容易になるだろうどちらtype
の$x
-の両方の事実X
とはY
含めることが起こる$abc
フィールドをも実証されているものとは無関係である
多くの人は、オブジェクトが関数に渡される方法と参照渡しが何を意味するかについて混乱するようです。オブジェクト変数は引き続き値で渡されますが、PHP5で渡される値は参照ハンドルです。証拠として:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
出力:
a, b
するには、参照によって渡す手段我々は、発信者によって見られる変数を変更することができます。上記のコードは明らかにそうではありません。スワップ関数を次のように変更する必要があります。
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
出力:
b, a
参照渡しするため。
swap
機能。つまり、オブジェクトが「値渡し」された場合。一方、オブジェクトハンドルが関数に渡された場合に期待されることも、実際に行われることです。コードはこれら2つのケースを区別しません。
http://www.php.net/manual/en/migration5.oop.php
PHP 5には、新しいオブジェクトモデルがあります。PHPのオブジェクトの処理は完全に書き直され、パフォーマンスと機能が向上しています。以前のバージョンのPHPでは、オブジェクトはプリミティブ型(整数や文字列など)のように処理されていました。このメソッドの欠点は、意味的には、変数が割り当てられたとき、またはメソッドにパラメーターとして渡されたときにオブジェクト全体がコピーされることでした。新しいアプローチでは、オブジェクトは値ではなくハンドルによって参照されます(ハンドルはオブジェクトの識別子と考えることができます)。
PHP変数は値によって割り当てられ、値によって関数に渡されます。また、オブジェクトを含む/表すときは、参照によって渡されます。&を使用して、変数を参照渡しにすることができます。
値/参照例によって割り当て:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
出力します
var1:テスト、var2:最終テスト、var3:最終テスト
値渡し/参照例:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
出力:
var1:foo、var2 BAR
参照例によって渡されるオブジェクト変数:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
出力されます:
FOO
(その最後の例はおそらくもっと良いかもしれません...)
$foo
あるオブジェクトへのポインタ。$foo
でパラメータを宣言しなかったため、関数に値で渡されます。changeFoo()
changeFoo()
&
PHP5では、プリミティブ型を含む変数は値で渡されます。オブジェクトを含む変数は参照によって渡されます。2006年のLinux Journalには、これと他のオブジェクト指向の4と5の違いについて言及している興味深い記事があります。
&
。
オブジェクトは、PHP 5では参照渡し、PHP 4では値渡しされます。変数はデフォルトで値渡しされます。
ここをお読みください:http : //www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
&
。
&
のパラメーターの前で定義されていない場合でも関数によって変更できることを観察したと思います-それらが値によって渡された場合、パラメーターとして関数を呼び出したスコープに含まれるオブジェクトは影響を受けません。
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
参照によって渡されない場合でも属性は変更可能であるため、注意してください。
出力:
SwapObjects:b、a SwapValues:a、b
将来これに遭遇した人のために、匿名ユーザーが投稿したPHPドキュメントからこの宝石を共有したいと思います。
ここには混乱があるようです。ポインタと参照の違いは特に役に立ちません。すでに投稿されている「包括的な」例のいくつかの動作は、より単純な統一用語で説明できます。たとえば、Hayleyのコードは、期待どおりに正確に動作しています。(> = 5.3を使用)
最初の原則:ポインターは、オブジェクトにアクセスするためのメモリアドレスを格納します。オブジェクトが割り当てられるたびに、ポインタが生成されます。(私はまだZendエンジンについて深く掘り下げていませんが、私の知る限り、これは当てはまります)
第2の原則、そして最も混乱の元:関数への変数の受け渡しは、デフォルトでは値の受け渡しとして行われます。つまり、コピーで作業しています。「しかし、オブジェクトは参照によって渡されます!」こことJavaの世界の両方でよくある誤解。私は何のコピーを言ったことはありません。デフォルトの受け渡しは値によって行われます。常に。ただし、コピーされて渡されるのはポインタです。"->"を使用する場合は、もちろん、呼び出し元関数の元の変数と同じ内部にアクセスします。"="を使用するだけで、コピーのみが再生されます。
3番目の原則:「&」は、別の変数名/ポインターを、分離するまで、他のものと同じメモリアドレスに自動的かつ永続的に設定します。ここでは「エイリアス」という用語を使用するのが正しいです。"unset()"で強制的に分離されるまで、ヒップで2つのポインタを結合すると考えてください。この機能は、同じスコープ内と、引数が関数に渡される場合の両方に存在します。多くの場合、渡された引数は「参照」と呼ばれます。これは、「値による受け渡し」と「参照による受け渡し」の違いがCおよびC ++で明確になったためです。
ただ覚えておいてください。オブジェクト自体ではなく、オブジェクトへのポインタが関数に渡されます。パラメータリストで "&"を使用して実際にオリジナルを渡す場合を除き、これらのポインタはオリジナルのコピーです。オブジェクトの内部を掘り下げるときのみ、オリジナルが変更されます。
そして、ここにそれらが提供する例があります:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
私はJavaScriptについてこのテーマについて詳細なブログ記事を書きましたが、 PHP、C ++、および参照渡しと値渡しについて混乱していると思われる他の言語にも同様に当てはまると思います。
明らかに、C ++と同様に、PHPは参照渡しをサポートする言語です。デフォルトでは、オブジェクトは値で渡されます。オブジェクトを格納する変数を操作する場合、それらの変数をポインターとして見ると役立ちます(アセンブリレベルでは、それが基本的には変数だからです)。ポインタを値で渡す場合でも、ポインタを「トレース」して、ポイントされているオブジェクトのプロパティを変更できます。できないことは、別のオブジェクトを指すようにすることです。パラメータを参照渡しとして明示的に宣言した場合にのみ、それを行うことができます。
バージョンによって異なりますが、4は値によるもので、5は参照によるものです。