PHP Conference Japan 2024

什么是引用

PHP 中的引用是一种通过不同的名称访问相同变量内容的方法。它们不像 C 指针;例如,您不能使用它们执行指针算术运算,它们不是实际的内存地址,等等。请参阅引用不是什么以获取更多信息。相反,它们是符号表别名。请注意,在 PHP 中,变量名和变量内容是不同的,因此相同的内容可以具有不同的名称。最接近的类比是 Unix 文件名和文件 - 变量名是目录条目,而变量内容是文件本身。引用可以比作 Unix 文件系统中的硬链接。

添加注释

用户贡献的注释 3 条注释

273118949 at qq dot com
7 年前
就像一个人有两个不同的名字。
匿名
6 年前
与 C 不同,PHP 引用不被视为预解除引用的指针,而是完整的别名。

它们正在为其创建别名(“引用”)的数据在所有对它的引用都移除之前不会被垃圾回收。

“常规”变量本身被视为引用,并且出于垃圾回收的目的,它们与使用 =& 赋值的变量没有区别。

以下示例提供了说明。

1) 当被视为包含值的变量时,引用按预期的方式工作。但是,它们实际上是引用原始数据的对象。

<?php
var = "foo";
$ref1 =& $var; // 新的对象,引用 $var
$ref2 =& $ref1; // 直接引用 $var,而不是 $ref1!!!!!

echo $ref; // >foo

unset($ref);

echo
$ref1; // >Notice: Undefined variable: ref1
echo $ref2; // >foo
echo $var; // >foo
?>

2) 当通过引用访问时,原始数据在所有对它的引用都移除之前不会被移除。这包括引用和未使用 & 运算符赋值的“常规”变量,并且出于垃圾回收的目的,这两者之间没有区别。

<?php
$var
= "foo";
$ref =& $var;

unset(
$var);

echo
$var; // >Notice: Undefined variable: var
echo $ref; // >foo
?>

3) 要删除原始数据而不删除所有对它的引用,只需将其设置为 null。

<?php
$var
= "foo";
$ref =& $var;

$ref = NULL;

echo
$var; // 值为 NULL,因此不打印任何内容
echo $ref; // 值为 NULL,因此不打印任何内容
?>

4) 将数据放入数组也被视为向其添加一个引用,用于垃圾回收。

有关更多信息,请参阅https://php.net/manual/en/features.gc.refcounting-basics.php
aldo dot caruso at argencasas dot com
5 年前
以下三个代码片段显示了在不同情况下使用标量变量、数组和对象中的引用的效果。

在任何情况下,如果您坚持引用是变量的别名的概念,则结果都是预期的。在通过引用赋值后(无论 $a =& $b 还是 $b =& $a),两个变量名都指向同一个变量。

带标量的引用

<?php
/*
引用是同一变量的别名
*/

$a = 1;
$b =& $a;

$b = 2;
echo
"$a,$b\n"; // 2,2

$a = 3;
echo
"$a,$b\n"; // 3,3

// 变量可以在赋值之前绑定
$c =& $d;
$c = 4;
echo
"$c,$d\n"; // 4,4
?>

带数组的引用

<?php
/*
数组元素引用标量变量
*/

$a = 1;
$b = 2;
$c = array(&$a, &$b);

$a = 3;
$b = 4;
echo
"c: $c[0],$c[1]\n"; // 3,4

$c[0] = 5;
$c[1] = 6;
echo
"a,b: $a,$b\n"; // 5,6

/*
数组之间的引用
*/

$d = array(1,2);
$e =& $d;

$d[0] = 3;
$d[1] = 4;
echo
"e: $e[0],$e[1]\n"; // 3,4

$e[0] = 5;
$e[1] = 6;
echo
"d: $d[0],$d[1]\n"; // 5,6

$e = 7;
echo
"d: $d\n"; // 7 ( $d 不再是数组,而是一个整数 )

/*
使用 foreach 结构迭代引用数组
*/

$a = 1;
$b = 2;
$f = array(&$a,&$b);

foreach(
$f as $x) // 如果 $x 按值赋值,则不会更改引用的变量。
$x = 3;
echo
"a,b: $a,$b\n"; // 1,2

foreach($f as &$x) // 如果 $x 按引用赋值,则会更改引用的变量。
$x = 3;
echo
"a,b: $a,$b\n"; // 3,3

// 请注意,循环结束后,$x 仍然引用 $f[1],因此也引用 $b
$x = 4;
echo
"a,b: $a,$b\n"; // 3,4 ( $b 受影响 )

// 为了避免上述副作用,建议取消设置 x,将其与 $f[1] 和 $b 断开链接
unset($x);
$x = 5;
echo
"a,b: $a,$b\n"; // 3,4 ( $b 不受影响 )
?>

对象引用

<?php
/*
对象属性引用标量变量
*/

$a = 1;
$b = new stdClass();
$b->x =& $a;

$a = 2;
echo
"b->x: $b->x\n"; // 2

$b->x = 3;
echo
"a: $a\n"; // 3

/* 对象之间的引用 */
$c = new stdClass();
$c->x = 1;
$d =& $c;

$d->x = 2;
echo
"c->x: $c->x\n"; // 2

$d = new stdClass();
$d->y = 3;
echo
"c->y: $c->y\n"; // 3
echo "c->x: $c->x\n"; // 未定义属性: stdClass::$x
?>
To Top