FOR и FOREACH: ссылки и указатели
Давайте представим какую-нибудь тривиальную (не очень, но достаточно простую) задачу. Допустим, мы хотим к каждой строке в массиве добавить длину строки.
Напишем простейший цикл:
Давайте попробуем по-старинке:
Длинно? Но зато в итоге мы получили то, что хотели. Почему? Дело в том, что во втром случае с циклом for мы работаем с самим исходным массивом, а в первом (foreach) - с копиями элементов массива.
Поясню. При каждом проходе цикла в нашем случае переменной $str присваивается значение очередного элемента исходного массива, и работая дальше с переменной $str, мы используем это значение, но не сам элемент. То есть, воздействуя на копию элемента массива - мы не затрагиваем исходный массив.
Вот тут-то пора вспомнить о ссылках. Ссылка на переменную - это не новая переменная, а адрес, указатель на область памяти, где хранится исходная переменная. Напишем так:
Вот теперь, когда мы не создаем новую переменную $str и копируем в неё значение элемента массива, а создаем указатель $str на область памяти, где этот элемент хранится, всё работает правильно!
Напишем простейший цикл:
foreach ($big_arr as $str)
$str .= " ".strlen($str);Однако, распечатав массив
print_r($big_arr);мы увидим, что не достигли результата, элементы массива остались без изменения. В чем же дело? Давайте разберемся.
Давайте попробуем по-старинке:
for ($i=0;$i<count($big_arr);$i++)
$big_arr[$i] .= " ".strlen($big_arr[$i]);
Длинно? Но зато в итоге мы получили то, что хотели. Почему? Дело в том, что во втром случае с циклом for мы работаем с самим исходным массивом, а в первом (foreach) - с копиями элементов массива.
Поясню. При каждом проходе цикла в нашем случае переменной $str присваивается значение очередного элемента исходного массива, и работая дальше с переменной $str, мы используем это значение, но не сам элемент. То есть, воздействуя на копию элемента массива - мы не затрагиваем исходный массив.
Вот тут-то пора вспомнить о ссылках. Ссылка на переменную - это не новая переменная, а адрес, указатель на область памяти, где хранится исходная переменная. Напишем так:
foreach ($big_arr as &$str) $str .= " ".strlen($str);Что мы здесь делаем? Теперь мы присваиваем переменной $str не значение очередного элемента массива, а адрес в памяти, где этот элемент хранится, и значит при работе с переменной $str мы будем напрямую работать с этим элементом.
Вот теперь, когда мы не создаем новую переменную $str и копируем в неё значение элемента массива, а создаем указатель $str на область памяти, где этот элемент хранится, всё работает правильно!
Комментарии
Отправить комментарий