Я хотел бы знать, как побочные эффекты назначения переменной PHP по ссылке работают под капотом (обратите внимание, я спрашиваю о назначении переменной, не передавая аргумент по ссылке на функцию; как в C ++, эти два могут быть различными, и PHP запрограммировал эти две операции отдельно под капотом).
В основном, я ищу объяснение для следующего:
$a = array(111, 222, 333);
$dummyReferenceVariable = &$a[0];
$b = $a;
$b[0] = "change everything: both a[0] and b[0]";
После создания фиктивной переменной присваиваем $b[0]
изменится $a[0]
даже если $dummyReferenceVariable
никогда не используется. Зачем?
Чтобы увидеть, как работают такие побочные эффекты, рассмотрите следующий фрагмент:
$a = array(111, 222, 333);
$b = $a;
$b[0] = 999;
var_dump($a, $b);
$dummyReferenceVariable = &$a[0];
$dummyReferenceVariable = 444;
var_dump($a, $b);
$c = $a;
$d = $b;
var_dump($a, $b, $c, $d);
$a[0] = 555;
$b[0] = 666;
$c[0] = 777;
$d[0] = 888;
var_dump($a, $b, $c, $d);
Я проиллюстрирую, что происходит под капотом, со следующими диаграммами (то, что происходит внутри, когда массивы назначаются по значению, уже покрыто эта почта), чей пример в своем ответе начинается так же, как этот, хотя заданный вопрос является другим:
ПРИМЕЧАНИЕ: на диаграммах оранжевые ссылки вести себя так, что когда массиву, к которому принадлежит указывающий элемент массива, назначен, соответствующий элемент массива в копии массива будет указывать на то же место с копирование при записи отключено. С другой стороны, черные ссылки указать, что при назначении элемента массива значение будет скопировано в новую ячейку памяти (копирование при записи):
Просто, чтобы подчеркнуть, вот результат программы:
array(3) {
[0]=>
int(111)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
int(999)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
&int(444)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
int(999)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
&int(444)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
int(999)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
&int(444)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
int(999)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
&int(777)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
int(666)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
&int(777)
[1]=>
int(222)
[2]=>
int(333)
}
array(3) {
[0]=>
int(888)
[1]=>
int(222)
[2]=>
int(333)
}
Заметка. Эта особенность имеет место только при назначении ссылок на элементы массива, как подтверждает следующий простой фрагмент:
// ASSIGNING REFERENCE VALUES TO SCALARS (INSTEAD OF ARRAY ELEMENTS) WORK AS EXPECTED:
$a = 111;
$aRef = &$a;
$a = 222;
var_dump($a, $aRef); // 222, 222
$aRef = 333;
var_dump($a, $aRef); // 333, 333
$c = $a;
$d = $aRef;
$c = 444;
$d = 555;
var_dump($a, $aRef, $c, $d); // 333, 333, 444, 555
который выводит следующее, как и ожидалось:
int(222)
int(222)
int(333)
int(333)
int(333)
int(333)
int(444)
int(555)
Вот что происходит под капотом в вышеупомянутом случае скаляров:
Других решений пока нет …