中的引用与深浅拷贝
PHP 中的变量赋值默认是值拷贝,理解引用和拷贝机制对避免 Bug 很重要。
基础赋值(值拷贝)
php
$a = 5;
$b = $a; // 值拷贝,$b 是 $a 的副本
$b = 10;
echo $a; // 5,$a 不受影响
echo $b; // 10引用赋值
使用 & 符号创建引用,两个变量指向同一个内存地址:
php
$a = 5;
$b = &$a; // 引用赋值
$b = 10;
echo $a; // 10,$a 也被修改了
// 取消引用
unset($b); // $a 仍然是 10数组中的引用陷阱
php
// 问题:foreach 中使用引用
$arr = [1, 2, 3];
foreach ($arr as &$value) {
$value *= 2; // 意图:每个元素乘以2
}
// 结果:[2, 4, 6]
// 危险:引用未被销毁
foreach ($arr as $value) {
// 这里会出问题,因为 $value 仍然是引用
}
// 结果可能是 [2, 4, 4] 而非预期
// 正确做法:unset 引用
unset($value);深拷贝 vs 浅拷贝
php
// 浅拷贝:对象赋值默认是引用
$obj1 = new stdClass();
$obj1->name = '张三';
$obj2 = $obj1; // 引用
$obj2->name = '李四';
echo $obj1->name; // 李四
// 深拷贝:使用 clone
$obj3 = clone $obj1;
$obj3->name = '王五';
echo $obj1->name; // 李四,$obj1 不受影响
// 深拷贝对象(含嵌套对象)
class Person {
public $name;
public $address; // 另一个对象
public function __clone() {
// 克隆时深拷贝嵌套对象
$this->address = clone $this->address;
}
}函数参数中的引用
php
// 传递引用,可以修改原变量
function swap(&$a, &$b) {
$temp = $a;
$a = $b;
$b = $temp;
}
$x = 1;
$y = 2;
swap($x, $y);
echo "$x, $y"; // 2, 1
// 返回引用
function &getValue() {
static $value = 0;
return $value;
}
$val = &getValue();
$val = 5; // 修改静态变量注意事项
- 引用不是指针,不能对引用做指针运算
- 过度使用引用会降低代码可读性
- 对象默认是引用传递,不需要加
& - 函数参数中使用引用时要小心,可能产生副作用