PHP变量引用与内存地址理解
PHP的引用和C语言的指针不同。理解引用的底层机制可以避免很多bug。今天说说PHP变量引用的原理。
引用的创建。
```php
$a = 10;
$b = &$a;
$b = 20;
echo "a: $a, b: $b\n"; // 20, 20
// 引用计数
$x = "Hello";
$y = &$x;
$z = &$x;
unset($y);
echo $x . "\n"; // Hello($z还在引用)
unset($z);
echo $x . "\n"; // 空(所有引用都断开)
?>
函数参数引用。
```php
function addItem(array &$arr, mixed $item): void
{
$arr[] = $item;
}
$list = [1, 2, 3];
addItem($list, 4);
print_r($list);
// 引用返回
class Container
{
private array $data = [];
public function &get(string $key): mixed
{
return $this->data[$key];
}
}
$container = new Container();
$value = &$container->get('name');
$value = '张三';
// 直接修改了Container内部的data
?>
foreach中的引用。
```php
$arr = [1, 2, 3, 4, 5];
foreach ($arr as &$value) {
$value *= 2;
}
unset($value); // 必须解除引用
print_r($arr);
// 如果没有unset,后面的代码中使用$value会影响数组最后一个元素
?>
引用的解除。
```php
$a = 10;
$b = &$a;
$b = &$d; // 重新绑定,$a不再受影响
$b = 30;
echo $a . "\n"; // 10
echo $b . "\n"; // 30
// unset只断开变量名和值的绑定
$a = 10;
$b = &$a;
unset($b);
echo $a . "\n"; // 10($a不受影响)
?>
对象和引用的关系。
```php
// 对象默认是通过引用传递的
class User
{
public string $name;
}
function changeName(User $user): void
{
$user->name = '修改后';
}
$user = new User();
$user->name = '原始';
changeName($user);
echo $user->name . "\n"; // 修改后
// clone创建副本
function changeNameClone(User $user): void
{
$user = clone $user;
$user->name = '克隆修改';
}
changeNameClone($user);
echo $user->name . "\n"; // 修改后(不受clone修改影响)
?>
引用是PHP中容易混淆的概念。引用和指针不同,引用是符号表别名。foreach中的引用要记得unset。对象参数默认是引用传递。理解引用的行为可以避免很多难以发现的bug。
PHP变量引用与内存地址理解