References in PHP are a means to access the same variable content by different names and they are not actual memory addresses. Instead, they are symbol table aliases. And, when an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
另一方面,我知道,标识符是赋予实体的名称(而不是像 PHP 中的引用那样的内存位置)。您能解释一下 PHP 中“标识符”和“引用”之间的区别吗?
最佳答案
让我们从报价的最后部分开始。
And, when an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
对象标识符
一般来说,对象标识符是标识对象的整数值。让我们从一个裸类 A
创建一些对象。我们将使用 SPL 的 spl_object_id()
和 var_dump()
函数。
这两个函数都返回给定对象的对象句柄。 对象句柄不是内存地址。
class A {}
$a = new A();
$b = $a;
var_dump($a) . PHP_EOL;
var_dump($b) . PHP_EOL;
// object(A)#1 (0) { Notice #1 - an identifier
// }
// object(A)#1 (0) { Notice #1 - an identifier
// }
echo spl_object_id($a) . PHP_EOL; // Outputs: 1 - an identifier
echo spl_object_id($b) . PHP_EOL; // Outputs: 1 - an identifier
$a
和 $b
保存标识符的副本,它指向同一对象 (A)。
如果 PHP 脚本创建了 500 个对象,则每个对象 id 在该对象的生命周期中都是唯一的。每个对象id都可以用作存储对象或识别对象的 key ,只要该对象没有被破坏/垃圾收集。一旦对象被销毁,它的 id 就可以被其他对象重用。
现在,让我们从您报价的第一部分开始。
References in PHP are a means to access the same variable content by different names and they are not actual memory addresses. Instead, they are symbol table aliases.
引用
在 PHP 中,引用有不同的含义。因此,它允许您访问具有不同变量名称的值。 PHP 中的引用是由 & 运算符创建的:
$a = 12;
// Notice the & (ampersand)
$b = & $a; // $b = 12;
$b = 20; // $a = 20; now
这里我们可以使用$a
和$b
访问值20
。好的!我们现在需要知道当我们为变量赋值时会发生什么因为您引用了不同的变量名称实际上并不是内存地址。让我们深入探讨一下。
zval 容器
PHP 变量存储在名为 zval 的容器中。当使用常量值创建新变量时,就会创建 zval 容器,例如:
$a = "hello";
zval 容器存储有关变量的四种类型的信息:
- 类型 - 变量的类型
- Value - 变量的值
- is_ref - 一个 bool 值,表示变量是否是“引用集”的一部分
- refcount - 保存有多少个变量名称(也称为符号)指向这个 zval 容器
有一个名为xdebug_debug_zval()
的函数,当安装Xdebug
时可用;它可以帮助您深入了解具有值的变量如何驻留在 zval 容器中。
$a = "hello";
xdebug_debug_zval('a');
输出如下:
a: (refcount=1, is_ref=0)='hello'
或者以图形方式,您可以将 zval 容器想象为如下所示:
符号表
zval 容器不包含变量名称。它们存储在所谓的符号表中。在符号表中,我们的“引用”部分的示例如下所示:
symbol | value
-------+------
a, b | 20
所以 a
和 b
符号在这里是别名。这种情况仅发生在标量类型上。
PHP 中有四种类型的作用域 - 本地、全局、静态和函数参数。每个级别的范围都有一个符号表。与标量值相反,数组和对象将它们的属性存储在它们自己的符号表中。在符号表中,“对象标识符”部分的示例如下所示:
$a = new A();
$b = $a;
symbol | value object | details
-------+--------- -------------+--------
a | object(A)#1 object(A)#1 | class A { ... }
b | object(A)#1
这里的a
和b
符号不是别名。它们持有标识符的副本,该副本指向同一个对象。
引用文献:
关于php - PHP编程语言中 'identifier'和 'reference'概念有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61228494/