Давайте начнем с последней части вашей цитаты.
И, когда объект передается по аргументу, возвращается или присваивается другой переменной, различные переменные не являются псевдонимами: они содержат копия идентификатора, который указывает на тот же объект.
Идентификаторы объекта
В общем, идентификатор объекта - это целочисленное значение, которое идентифицирует объект. Давайте создадим несколько объектов из голого класса 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 как следующее:
Таблица символов
Контейнер 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
не являются псевдонимами. Они содержат копию идентификатора, который указывает на один и тот же объект.
Ссылки:
- https://www.php.net/manual/en/features.gc.refcounting-basics.php
- http://www.levijackson.net/php-zvals-and-symbol-tables/
- Объекты и ссылки в php 5
- https://github.com/php/php-src/pull/2611
- https://github.com/php/php-src/commit/5097e2ee13de12b4445b4123e1554c0733c6853c