在PHP中对象真的是按引用传递的吗

433 查看

在PHP中使用对象的时候,我们总是被告知“默认情况下对象是按照引用传递的”,其实这是个误区,不完全正确。PHP的对象变量存储的是此对象的一个标示符而不是对象值,通过此标示符可以访问真正的对象的内容,那么在对象作为参数被传递,作为结果返回,或者赋值给另外一个变量时,其实传递的就是这个标示符,他们之间的关系是两个变量都保持了同一标示符的拷贝,而并不是引用。

我们从下面的示例来分析

PHPclass A {};
class B {};
$a = new A;
$b = $a;    
$b->testA = "Changed Class A";

/*
 * 此时$a,$b的关系:
 *        +-----------+      +-----------------+
 * $a --> | object id | ---> | object(Class A) |
 *        +-----------+      +-----------------+
 *                               ^
 *        +-----------+          |
 * $b --> | object id | ---------+
 *        +-----------+    
 *
 *
 */

$c = new B;
$a = $c;
$a->testB = "Changed Class B";

/*
 * 此时$a,$b,$c的关系:
 *        +-----------+      +-----------------+
 * $b --> | object id | ---> | object(Class A) |
 *        +-----------+      +-----------------+
 *                               
 *        +------------+          
 * $a --> | object id2 | -------------+
 *        +------------+              |
 *                                    v
 *        +------------+      +-----------------+
 * $c --> | object id2 | ---> | object(Class B) |
 *        +------------+      +-----------------+
 */

var_dump($a); //["testB"]=> string(15) "Changed Class B"
var_dump($b); //["testA"] => string(15) "Changed Class A"
var_dump($c); //["testB"]=> string(15) "Changed Class B"
//如果对象是按照引用传递的,那么$a, $b, $c输出的内容应该一样,事实上结果并非如此。 看下面通过引用传递对象的列子:

<?php
$aa = new A;
$bb = &$aa;  // 引用 
$bb->testA = 2;

/*
 * 此时$aa, $bb的关系:
 *
 *         +-----------+      +-----------------+
 * $bb --> | object id | ---> | object(Class A) |
 *         +-----------+      +-----------------+
 *              ^                  
 *              |
 * $aa ---------+ 
 *
 *
 */

$cc = new B;
$aa = $cc;
$aa->testB = "Changed Class B";

/*
 * 此时$aa, $bb, $cc的关系:
 *
 *         +-----------+      +-----------------+
 *         | object id | ---> | object(Class A) |
 *         +-----------+      +-----------------+
 *              
 * $bb ---->-----+      
 *               |
 * $aa ---->-----+
 *               |  
 *               v   
 *         +------------+      
 *         | object id2 | --------------+ 
 *         +------------+               |
 *                                      v
 *         +------------+      +-----------------+
 * $cc --> | object id2 | ---> | object(Class B) |
 *         +------------+      +-----------------+
 */

var_dump($aa); //["testB"]=>string(15) "Changed Class B"
var_dump($bb); //["testB"]=>string(15) "Changed Class B"
var_dump($cc); //["testB"]=>string(15) "Changed Class B"

//此时$aa,$bb,$cc三者内容完全一样,所以可以看出对象默认并不是按照引用传递,要尽快走出这个误区。

参考文章:http://php.net/manual/zh/language.oop5.references.php
http://weizhifeng.net/php-reference.html