Насколько я понимаю, здесь работает следующее:
$arr = array(1);
Что такое $arr
? Это объект, который указывает на некоторую область памяти.
Что расположено в этой памяти? Какое-то значение (в данном случае - массив значений).
$a =& $arr[0];
Что происходит, когда мы объявляем ссылку на элемент массива? Значение этого массива заменяется на ссылку на старое значение. Т.е. хранили число 3, после действия выше стали хранить ссылку на это число 3 (это хорошо видно по дампу).
$arr2 = $arr;
Что происходит, когда мы один массив присваиваем другому? Правильно - копируются значения из одного массива в другой. Но при этом эти значения разнесены по разным участкам памяти.
Соответственно, если в одном из элементов массива хранилась ссылка на какое-то значение/объект (т.е. значением будет являться ссылка на какую-то область памяти), то при копировании значений из одного массива в другой мы также скопируем и нашу ссылку.
Т.е. будет выделена некоторая область памяти, в которой расположено значение соответствующего элемента массива. Но поскольку данный элемент исходного массива является ссылкой, то и соответствующий элемент нового массива будет являться ссылкой на то же значение, что и в исходном.
А раз так, то ничего удивительного в этом нет.
Попробуйте сделать $arr2[] = 3
и посмотрите, что хранится в $arr
и в $arr2
- массивы различаются.
Если еще не понятно, попробую объяснить на пальцах.
- Есть массив
$arr = array(1)
.
- Делаем
$a =& $arr[0]
;
- В отдельную область памяти переносится значение
$arr[0]
- В
$arr[0]
помещается ссылка на только что выделенную память (т.е. создается ссылка на наше старое значение)
- Присваиваем массиву
$arr2
массив $arr
- Выполняется копирование значений массива
$arr
в массив $arr2
- Значение первого (и единственного) элемента
$arr
- ссылка на выделенную ранее память, поэтому в первый элемент нового массива копируется как раз ссылка на ранее выделенную память
- Получаем, что первый элемент массива
$arr
и первый элемент массива $arr2
ссылаются на одну и ту же область памяти
- Поэтому при изменении
$arr2[0]
так же меняется и $arr[0]
Но я не читал исходники, это только мои предположения. Поэтому возможно, что что-то я не так понимаю. Но в данной трактовке описанные вами проблемы (в том числе и для второго примера) вполне логичны.
Хотя даже если я прав (т.е. если при создании ссылки на элемент массива этот элемент начинает хранить ссылку), то непонятно, почему при создании ссылки на элемент массива этот элемент массива начинает хранить ссылку на исходное значение. Почему нельзя было сделать так, что создаваемая ссылка на элемент массива хранила бы адрес этого элемента?
Может быть, потому что
$arr = array(1, 2);
$arr[0] =& $arr[1];
$arr[1] =& $arr[0];
Т.е. после первого присваивания $arr[0]
тогда хранило бы ссылку на $arr[1]
, а после второго - $arr[1]
хранило бы ссылку на $arr[0]
. Т.е. каждый элемент хранил бы ссылку сам на себя через другой элемент. И тогда при получении значения $arr[0]
мы ушли бы в бесконечный цикл.
Хотя это только домыслы, точно я не знаю, все-таки сам PHP не пишу ))