摘自:http://php.net/manual/en/language.oop5.references.php

通过上面的这段描述,我们可以知道以下几个关键点:

  1.  从php 5 开始,一个对象变了不再保存对象自己本身,而是保存的an object identifier,类比于指针。通过object identifier可以访问到实际的对象。并且在对象的参数传递、返回值、赋值中,接收这些操作的变量得到的是object identifier,而不是引用(或者说别名)。
  2. a php reference 是别名,类似于linux的软连接。

也就是说正常情况下,对象的传递是传递的object identifier。而在加了&标志时,传递的才是引用(或者说是别名)。

 

进一步理解引用和object identifier有什么区别分

构造类如下:

 

 1 <?php
 2 class A{
 3     public $a;
 4     public $b;
 5     public function __construct($a,$b){
 6         $this->a=$a;
 7         $this->b=$b;
 8     }
 9     public function printContent(){
10         echo "a=$this->a  b=$this->b\n";
11     }
12 }

 

进行如下操作:

 1 $aa = new A(1,2);
 2 $bb = $aa;              //传递的是object identifier
 3 $cc = &$aa;              //$cc是对象aa的别名
4 $aa = new A(55,1); 5 echo '打印对象aa的内容'."\n"; 6 $aa->printContent();        //a=55  b=1 7 echo '打印对象bb的内容'."\n"; 8 $bb->printContent();        //a=1  b=2 9 echo '打印对象cc的内容'."\n"; 10 $cc->printContent();        //a=55  b=1

由上面的输出可知,当$aa的指向的内容发生变化时,因为$cc是$aa的别名,所以跟随变化。而$bb只是保存了在执行第二行语句时和$aa相同的object identifier,在执行第四行语句后,$aa保存的object identifier变成了新的对象A(55,1)的identifier,所以$bb不受影响。

进一步,查看参数传递过程中引用和identifier的差异:

定义以下两个方法:

1 function change($tmp){
2     $tmp = new A(2,3);
3     return $tmp;
4 }
5 function changeByRef(&$tmp){
6     $tmp = new A(4,5);
7     return $tmp;
8 }

执行如下操作:

 1 $aa = new A(1,2);
 2 echo '初始化时打印对象aa'."\n";
 3 $aa->printContent();                //a=1  b=2
 4 
 5 $bb = change($aa);
 6 echo '调用change方法后打印对象aa'."\n";
 7 $aa->printContent();                //a=1  b=2
 8 echo '调用change方法后打印返回的对象bb'."\n";
 9 $bb->printContent();                //a=2  b=3
10 
11 
12 $bb = changeByRef($aa);
13 echo '调用changeByRef方法后打印对象aa'."\n";
14 $aa->printContent();                //a=4  b=5
15 echo '调用change方法后打印返回的对象bb'."\n";
16 $bb->printContent();                //a=4  b=5

可见,当传递的是object identifier时,改变方法的参数的object identifier不会影响到被传递的对象(即$aa)。而传递的是别名时则会影响到。

需要注意的是:不论传递的是对象的object identifier或则引用,当在方法中修改对象的属性时,因为实际上修改地是相同的object,因此会影响到被传递的对象或者被引用的对象。

更多的对象与引用的实例说明可以参考以下代码:

摘自:http://php.net/manual/en/language.oop5.references.php

 

<?php
class Foo {
  private static $used;
  private $id;
  public function __construct() {
    $id = $used++;
  }
  public function __clone() {
    $id = $used++;
  }
}

$a = new Foo; // $a is a pointer pointing to Foo object 0
$b = $a; // $b is a pointer pointing to Foo object 0, however, $b is a copy of $a
$c = &$a; // $c and $a are now references of a pointer pointing to Foo object 0
$a = new Foo; // $a and $c are now references of a pointer pointing to Foo object 1, $b is still a pointer pointing to Foo object 0
unset($a); // A reference with reference count 1 is automatically converted back to a value. Now $c is a pointer to Foo object 1
$a = &$b; // $a and $b are now references of a pointer pointing to Foo object 0
$a = NULL; // $a and $b now become a reference to NULL. Foo object 0 can be garbage collected now
unset($b); // $b no longer exists and $a is now NULL
$a = clone $c; // $a is now a pointer to Foo object 2, $c remains a pointer to Foo object 1
unset($c); // Foo object 1 can be garbage collected now.
$c = $a; // $c and $a are pointers pointing to Foo object 2
unset($a); // Foo object 2 is still pointed by $c
$a = &$c; // Foo object 2 has 1 pointers pointing to it only, that pointer has 2 references: $a and $c;
const ABC = TRUE;
if(ABC) {
  $a = NULL; // Foo object 2 can be garbage collected now because $a and $c are now a reference to the same NULL value
} else {
  unset($a); // Foo object 2 is still pointed to $c
}

 

 

 

 

 

 

posted on 2017-03-26 16:11  jade640  阅读(388)  评论(0编辑  收藏  举报