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

标签 php object reference identifier

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 容器想象为如下所示:

enter image description here

符号表

zval 容器不包含变量名称。它们存储在所谓的符号表中。在符号表中,我们的“引用”部分的示例如下所示:

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

所以 ab 符号在这里是别名。这种情况仅发生在标量类型上。

PHP 中有四种类型的作用域 - 本地、全局、静态和函数参数。每个级别的范围都有一个符号表。与标量值相反,数组对象将它们的属性存储在它们自己的符号表中。在符号表中,“对象标识符”部分的示例如下所示:

$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

关于php - PHP编程语言中 'identifier'和 'reference'概念有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61228494/

相关文章:

php - 如何从网页打印特定表格

php - 根据某些列值拆分 foreach 循环

php - PHP 序列化函数是否兼容 UTF-8?

c++ - 在 XY 点数组中找到三个 XY 点的最大面积

java - Java 中每个共享引用是否占用另一个内存字(例如 32 或 64 位)?

reference - 什么是软件开发引用的最佳在线图书服务?

php - 拉拉维尔 5.3 : Cannot add Additional user info for User registration

javascript - 无法访问数组中对象的属性

java - 当android按 Intent 传递对象时,是按值还是按引用值完成

Java - 将 null 作为参数传递给 print()