PHP 编程语言中的 'identifier' 和 'reference' 概念有什么区别?

What is the differences between 'identifier' and 'reference' concepts in PHP programming language?

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 中的引用那样的内存位置)。您能解释一下 'identifier' 和 'references' 中 PHP 在这种情况下的区别吗?

php 中的引用意味着您允许在进一步的代码或处理中更改特定变量的值,例如

$x =& $y

或者

$x = &$y 如果在进一步的代码中更改 $y 的值,这两个都允许更改 $x 的值。

而标识符只是一个分配的名称,不能在进一步的过程中更改其值。

让我们从您报价的最后一部分开始。

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.

对象标识符

通常,对象标识符是标识对象的整数值。让我们从裸 class A 创建一些对象。我们将使用 SPL 的 spl_object_id()var_dump() 函数。

这两个函数 return 给定对象的 对象句柄 对象句柄不是内存地址

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 都可以用作存储对象的键,或用于标识对象,只要该对象未被 destroyed/garbage 收集即可。一旦对象被销毁,其 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 容器存储关于变量的四种信息:

  • Type - 变量的类型
  • Value - 变量的值
  • is_ref - 一个布尔值,表示变量是否是 "reference set"
  • 的一部分
  • refcount - 保存有多少变量名(也称为符号)指向这个 zval 容器

有一个名为xdebug_debug_zval()的函数,安装Xdebug后可用;它可以帮助您深入了解具有值的变量如何驻留在 zval 容器中。

$a = "hello";
xdebug_debug_zval('a');

输出结果如下:

a: (refcount=1, is_ref=0)='hello'

或者在图形上你可以想象 zval 容器如下:

符号Table

zval 容器不包含变量名。这些存储在所谓的符号 table 中。在符号 table 中,我们的 "Reference" 部分的示例如下所示:

symbol | value
-------+------
a, b   | 20

所以ab符号在这里是别名。这只发生在标量类型上。

PHP 中有四种作用域 - 局部、全局、静态和函数参数。每个级别的范围都有一个符号 table。与标量值相反,arraysobjects 将它们的属性存储在它们自己的符号 table 中。在符号 table 中,我们的 "Object Identifiers" 部分的示例如下所示:

$a = new A();
$b = $a;

symbol | value                object   | details
-------+---------         -------------+--------
a      | object(A)#1       object(A)#1 | class A { ... }
b      | object(A)#1

这里的ab符号不是别名。它们持有标识符的副本,指向同一个对象。

参考文献:

  1. https://www.php.net/manual/en/features.gc.refcounting-basics.php
  2. http://www.levijackson.net/php-zvals-and-symbol-tables/
  3. Objects and references in php 5
  4. https://github.com/php/php-src/pull/2611
  5. https://github.com/php/php-src/commit/5097e2ee13de12b4445b4123e1554c0733c6853c