Копирование при записи и reset

Когда-то в ПХП жили без копирования при записи (copy-on-write). Думаю некоторые олдскульщики ещё помнят, как когда-то приходилось для экономии обмазывать всё ссылками. Копирование при записи очень облегчает жизнь, но настолько расслабляет, что всё реже задумываешься как всё работает под капотом.

Многие ли увидят тут проблему?

function array_first(array $array)
{
	return reset($array);
}

Проблема в том, что reset меняет внутреннее состояние массива, а значит вызывает копирование при записи — в этот момент массив будет удвоен. Это небольшая неприятность для небольших массивов, но если в нём миллион элементов…

Короче, можно не заметить как исчерпаешь память. Кстати, ПХП тут мог бы делать оптимизацию (но не делает) — не менять указатель, если до вызова reset он был на первом элементе. В этом конкретном примере такая оптимизация иногда могла бы экономить память.

Но в общем случае использование тут reset — плохая идея, на мой взгляд, лучше сделать так:

function array_first(array $array)
{
	return current(array_slice($array, 0, 1));
}

Ту же проблему (с удвоением массива) содержит в себе и до сих пор встречающаяся итерация через each или next — вызов этих функций так же модифицирует внутренний указатель массива. Впрочем лечится легко — использованием foreach.

К слову, в ПХП 7.2 функция each объявлена устаревшей.

Поделиться
Отправить
Популярное