赋值运算将原变量的值拷贝到新变量中(传值赋值),所以改变其中一个并不影响另一个。这也适合于在密集循环中拷贝一些值例如大数组。
在 PHP 中普通的传值赋值行为有个例外就是碰到对象 object 时,是以引用赋值的,除非明确使用了 clone 关键字来拷贝。
<?php
$a = 3;
$b = $a;
$a = 4;
echo $a, ' ', $b, "\r\n";
$arr1 = [1, 2];
$arr2 = $arr1;
$arr2[0] *= 10;
echo json_encode($arr1), ' ', json_encode($arr2), "\r\n";
class A {
public $b;
}
$o1 = new A();
$o1->b = "aaa";
echo json_encode($o1), "\r\n";
$o2 = $o1;
$o2->b = 'bbbb';
echo json_encode($o1), ' ';
echo json_encode($o2), "\r\n";
输出结果
结果说明,只有对象是按引用赋值的,其他都是直接拷贝赋值的
PS D:\code\php> php reference.php
4 3
[1,2] [10,2]
{"b":"aaa"}
{"b":"bbbb"} {"b":"bbbb"}
<?php
class Eye {
public $color;
public function __construct($color)
{
$this->color = $color;
}
}
class Hair {
public $color;
public function __construct($color)
{
$this->color = $color;
}
}
class Cat {
public $eye;
public $hair;
public $weight;
public function __construct($eye, $hair, $weight)
{
$this->eye = $eye;
$this->hair = $hair;
$this->weight = $weight;
}
public function __toString()
{
return "{$this->eye->color}眼睛,{$this->hair->color}毛,重{$this->weight}斤\r\n";
}
}
//对象赋值,是引用赋值,所以修改是相关联的
$cat1 = new Cat(new Eye('黑'), new Hair('蓝'), 10);
echo $cat1; //黑眼睛,蓝毛,重10斤
$cat2 = $cat1;
$cat2->hair->color = '白';
$cat1->weight = 15;
echo $cat1; //黑眼睛,白毛,重15斤
echo $cat2; //黑眼睛,白毛,重15斤
//clone是浅复制,所有的引用属性(即对象比如Eye Hair)仍然会是一个指向原来的变量的引用
$cat3 = new Cat(new Eye('黑'), new Hair('蓝'), 10);
echo $cat3; //黑眼睛,蓝毛,重10斤
$cat4 = clone $cat3;
$cat4->weight = 16;
echo $cat3; //黑眼睛,蓝毛,重10斤
echo $cat4; //黑眼睛,蓝毛,重16斤
$cat4->eye->color = '褐';
echo $cat3; //褐眼睛,蓝毛,重10斤
echo $cat4; //褐眼睛,蓝毛,重16斤
//用序列号和反序列化可以实现深复制,变成两个不相互干扰的对象
$cat5 = new Cat(new Eye('黑'), new Hair('蓝'), 10);
echo $cat5; //黑眼睛,蓝毛,重10斤
$catstr = serialize($cat5);
$cat6 = unserialize($catstr);
$cat6->hair->color = '白';
$cat5->weight = 12;
echo $cat5; //黑眼睛,蓝毛,重12斤
echo $cat6; //黑眼睛,白毛,重10斤