Я столкнулся с этим, казалось бы, очень простым вопросом на днях How to changing value in $array2 without referring $array1? Однако чем больше я смотрел на него, тем более странным казалось, что это действительно работает по назначению. После этого я начал искать коды операций, которые генерируются из вывода следующего.Присвоить по ссылке ошибка
$array1 = array(2, 10);
$x = &$array1[1];
$array2 = $array1;
$array2[1] = 22;
echo $array1[1]; // Outputs 22
Это кажется сумасшедшим, чтобы мне так array2 должен быть только копией array1 и все, что происходит в одном массиве не должно повлиять на содержание другого. Конечно, если вы прокомментируете вторую строчку, финальная строка выйдет на 10, как ожидалось.
Глядя дальше Я мог бы классный сайт, который показывает мне коды операций, которые PHP создает с помощью Vulcan Logic Dumper. Вот коды операций, генерируемые вышеуказанным кодом.
Finding entry points
Branch analysis from position: 0
Return found
filename: /in/qO86H
function name: (null)
number of ops: 11
compiled vars: !0 = $array1, !1 = $x, !2 = $array2
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > INIT_ARRAY ~0 2
1 ADD_ARRAY_ELEMENT ~0 10
2 ASSIGN !0, ~0
4 3 FETCH_DIM_W $2 !0, 1
4 ASSIGN_REF !1, $2
5 5 ASSIGN !2, !0
6 6 ASSIGN_DIM !2, 1
7 OP_DATA 22, $6
8 8 FETCH_DIM_R $7 !0, 1
9 ECHO $7
10 > RETURN 1
Эти опкоды не документированы большой здесь http://php.net/manual/en/internals2.opcodes.php, но я верю в английском языке опкоды делают следующее. По линии ... может быть больше для меня, чем для кого-либо еще.
- Строка 3: Мы инициализируем массив с его первым значением, а затем добавляем 10 к нему, прежде чем назначать его массиву $ array1.
- Строка 4: Получить только для записи? значение из массива и назначить его ссылкой на $ x.
- Строка 5: Установите массив $ array1 в $ array2.
- Строка 6: Получить индекс массива 1. od_data Я предполагаю, что он устанавливает значение 22, хотя $ 6 никогда не возвращается. OD_DATA не имеет абсолютно никакой документации и не указана в качестве кода операции в любом месте, где я смотрел.
- Строка 8: выберите значение только для чтения из индекса 1 из массива $ array1 и повторите его.
Даже работая через коды операций, я не знаю, где это происходит. У меня есть ощущение отсутствия документации по кодам операций, и моя неопытность в работе с ними, вероятно, не позволяет мне понять, где это происходит.
EDIT 1:
Как отметил Майк в первом комментарии массивам ссылки сохраняется статус, когда они копируются. Здесь можно увидеть документацию вместе с местом в статье массива, которую она связывает с http://php.net/manual/en/language.types.array.php#104064. Это довольно смешно не считается предупреждением. Что удивительно для меня, если это так, статус ссылки не сохраняется для этого кода, как и следовало ожидать.
$array1 = array(2, 10);
$x = &$array1;
$array2 = $array1;
$array2[1] = 22;
echo $array1[1]; // Output is 10
Так кажется, что это происходит только тогда, когда вы пытаетесь назначить отдельные элементы по ссылке, делая эту функцию еще более запутанной.
Почему php сохраняет статус индексов массивов только когда они назначены индивидуально?
EDIT 2:
Я сделал некоторые испытания с использованием HHVM сегодня и HHVM обрабатывает первый надрез-его кода, как вы думаете, что это будет. Мне нравится PHP, но HHVM выглядит лучше и лучше по сравнению с Zend Engine.
См. Http://php.net/manual/en/language.types.array.php#104064 для чего. «Общие» данные остаются разделенными. –
Это кажется безумным для меня, поскольку вы на самом деле меняете структуру массивов, когда вы назначаете даже его части по ссылке. Плюс, если вы удалите [1] из строки 2, данные, разделяемые данными, не останутся прежними, так что это не совсем так. – mschuett
Начальное назначение - это просто псевдоним. Нельзя начинать манипулировать ими с помощью независимых операций, таких как '... []', которые они вынуждены расходиться. Это, безусловно, «неожиданно», но я бы не стал так говорить, что это «безумно». Хотя я доволен тем, что это был не очень хороший выбор, когда это было сделано, и PHP с тех пор застрял с ним. –