引用是什么

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

添加注释

用户贡献注释 4 则注释

273118949 at qq dot com
6 年前
这就像一个人有两个不同的名字一样。
匿名
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 受影响 )

// 为了避免之前的副作用,建议 unset $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"; // Undefined property: stdClass::$x
?>
anon
7 年前
总之,“&$reference” 表示“永远不要在这里复制值,而是进行写入”。按引用赋值不是赋值,而是“将 &$variable 设为引用,并且它的值永远不会被复制,同时让我正在赋值的变量也使用该值”。

要“取消引用/取消别名”,您必须取消设置或将显式副本复制到新变量中。

作为引用的对象属性将在克隆后继续存在并保持引用。通常情况下,数组中的引用和 PHP 的数组函数(combine、intersect、call_user_func、func_get_args 等)也是如此。

调用使用引用参数的函数将使提供的变量成为引用。当对参数使用可变数组展开时,也是如此;提供者的数组元素将成为引用。

一般情况下,不要使用它们,除非您正在处理底层调用,或者需要累加器等。对于设计不佳的函数,如果它们使用引用,请为它们提供一个副本进行修改。
To Top