В чем различия между понятиями «идентификатор» и «ссылка» в языке программирования PHP? - PullRequest
2 голосов
/ 15 апреля 2020

Ссылки в PHP являются средством доступа к одному и тому же переменному содержимому под разными именами, и они не являются реальными адресами памяти. Вместо этого они являются псевдонимами таблицы символов. И когда объект отправляется с помощью аргумента, возвращается или назначается другой переменной, различные переменные не являются псевдонимами: они содержат копию идентификатора, который указывает на тот же объект.

На с другой стороны, я знаю, что идентификатор - это имя, данное сущности (а не место в памяти, как ссылки в PHP). Можете ли вы объяснить различия между «идентификатором» и «ссылками» в PHP в этом контексте?

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Давайте начнем с последней части вашей цитаты.

И, когда объект передается по аргументу, возвращается или присваивается другой переменной, различные переменные не являются псевдонимами: они содержат копия идентификатора, который указывает на тот же объект.

Идентификаторы объекта

В общем, идентификатор объекта - это целочисленное значение, которое идентифицирует объект. Давайте создадим несколько объектов из голого класса 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 объектов, то каждый идентификатор объекта будет уникальным в течение всего времени существования объекта. Каждый идентификатор объекта можно использовать в качестве ключа для хранения объектов или для идентификации объекта, если объект не уничтожен / не подвергнут сборке мусора. Как только объект уничтожен, его идентификатор может быть повторно использован для других объектов.

Теперь давайте начнем с первой части цитаты.

Ссылки в PHP являются означает доступ к одному и тому же содержимому переменной под разными именами, и они не являются реальными адресами памяти. Вместо этого они являются псевдонимами таблицы символов.

Ссылка

В PHP, ссылка имеет другое значение. Следовательно, он позволяет получить доступ к значению с разными именами переменных. Ссылка создается оператором & в PHP:

$a = 12;

// Notice the & (ampersand)
$b = & $a; // $b = 12; 

$b = 20;   // $a = 20; now

Здесь мы можем получить доступ к значению 20, используя $a и $b. Хорошо! Теперь нам нужно знать, что происходит, когда мы присваиваем значение переменной , потому что вы указали, что разные имена переменных на самом деле не являются адресом памяти . Давайте копаться в этом.

zval Контейнер

Переменная PHP хранится в контейнере, который называется zval . Контейнер zval создается при создании новой переменной с постоянным значением, например:

$a = "hello";

В контейнере zval хранится четыре типа информации о переменной:

  • Тип - тип переменной
  • Значение - значение переменной
  • is_ref - логическое значение, представляющее, является ли переменная частью "набора ссылок"
  • 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

Так что a и b символы здесь являются псевдонимами. Это происходит только для скалярных типов.

В PHP есть четыре типа области действия: локальный, глобальный, stati c и параметры функции. Существует таблица символов для каждого уровня области видимости. В отличие от скалярных значений, массивы и объекты хранят свои свойства в собственной таблице символов. В таблице символов пример раздела «Идентификаторы объектов» выглядит следующим образом:

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

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

Здесь символы a и b не являются псевдонимами. Они содержат копию идентификатора, который указывает на один и тот же объект.

Ссылки:

  1. https://www.php.net/manual/en/features.gc.refcounting-basics.php
  2. http://www.levijackson.net/php-zvals-and-symbol-tables/
  3. Объекты и ссылки в php 5
  4. https://github.com/php/php-src/pull/2611
  5. https://github.com/php/php-src/commit/5097e2ee13de12b4445b4123e1554c0733c6853c
0 голосов
/ 15 апреля 2020

Refrence in php означает, что вы допускаете изменение значения переменной specfi c в дальнейшем коде или обработке, например

$x =& $y

или

$x = &$y Оба эти параметра позволяют изменять значение $x, если в последующем коде изменяется значение $y.

Принимая во внимание, что идентификаторы - это просто присвоенное имя и не могут изменить его значение в дальнейшем процессе.

...