Ответ 1
В принципе, есть два способа работы переменных в PHP...
Для всего, кроме объектов:
- Назначение по значению (означает, что копия возникает, если вы выполняете
$a = $b
. - Ссылка может быть достигнута путем выполнения
$a = &$b
(Обратите внимание, что оператор ссылки работает с переменной, а не с оператором присваивания, поскольку вы можете использовать ее в других местах)... - Копии используют технологию copy-on-write. Поэтому, если вы выполняете
$a = $b
, копия переменной памяти отсутствует. Но если вы затем сделаете$a = 5;
, память будет скопирована и перезаписана.
Для объектов:
- Назначение - по объектной ссылке. Это не совсем то же самое, что и нормальная переменная по ссылке (я объясню, почему позже).
- Скопировать по значению можно, выполнив
$a = clone $b
. - Ссылка может быть достигнута путем выполнения
$a = &$b
, но будьте осторожны, что это не имеет ничего общего с объектом. Вы привязываете переменную$a
к переменной$b
. Неважно, если это объект или нет.
Итак, почему присваивание объектам действительно не ссылается? Что произойдет, если вы выполните:
$a = new stdclass();
$b = $a;
$a = 4;
Что $b
? Ну, это stdclass
... Это потому, что он не пишет ссылку на переменную, а на объект...
$a = new stdclass();
$a->foo = 'bar';
$b = $a;
$b->foo = 'baz';
Что $a->foo
? Это baz
. Это потому что, когда вы сделали $b = $a
, вы говорите PHP, чтобы использовать тот же экземпляр объекта (следовательно, ссылку на объект). Обратите внимание, что $a
и $b
не являются одной и той же переменной, но оба они ссылаются на один и тот же объект.
Один из способов думать об этом - это думать обо всех переменных, которые хранят объект в качестве хранения указателя на этот объект. Таким образом, объект живет где-то в другом месте. Когда вы назначаете $a = $b
, где $b
- объект, все, что вы делаете, копирует этот указатель. Фактические переменные все еще не пересекаются. Но когда вы делаете $a = &$b
, вы сохраняете указатель на $b
внутри $a
. Теперь, когда вы управляете $a
, он каскадирует цепочку указателей на базовый объект. Когда вы используете оператор clone
, вы говорите PHP, чтобы скопировать существующий объект и создать новый с тем же состоянием... Итак, clone
действительно просто выполняет повальную копию varaible...
Итак, если вы заметили, я сказал, что объект не хранится в реальной переменной. Он хранится где-то еще, и в переменной хранится только указатель. Таким образом, это означает, что вы можете иметь (и часто иметь) несколько переменных, указывающих на один и тот же экземпляр. По этой причине внутреннее представление объекта содержит refcount
(просто количество числа переменных, указывающих на него). Когда refcount объекта падает до 0 (это означает, что все переменные, указывающие на него, либо выходят за пределы области видимости, либо меняются на somethign else), они собираются с мусором (поскольку они больше не доступны)...
Подробнее о ссылках и PHP в документах...
Отказ от ответственности: Некоторые из них могут быть упрощением или размытием определенных понятий. Я намеревался это только для того, чтобы быть руководством к тому, как они работают, а не точная разбивка того, что происходит внутри страны...
Изменить: О, и поскольку это "неуклюжий", я не думаю, что это так. Я думаю, что это действительно полезно. В противном случае вам будут передаваться переменные ссылки по всему месту. И это может привести к некоторым действительно интересным ошибкам, когда переменная в одной части приложения влияет на другую переменную в другой части приложения. И не потому, что он прошел, а потому, что ссылка была сделана где-то вдоль линии.
В общем, я не очень часто использую ссылки на переменные. Редко, что я нахожу их честной. Но я все время использую ссылки на объекты. Я использую их так много, что я рад, что они по умолчанию. В противном случае мне нужно будет написать некоторый оператор (поскольку &
обозначает ссылку на переменную, для обозначения ссылки на объект должен быть другой). И учитывая, что я редко использую clone
, я бы сказал, что 99,9% случаев использования должны использовать ссылки на объекты (так что оператор должен использоваться для случаев с более низкой частотой)...
JMHO
Я также создал видео, объясняющее эти различия. Проверьте на YouTube.