2012-05-26 4 views
5

В PHP документации говорится:Возвращение по ссылке

Не используйте возврат по ссылке для увеличения производительности. Двигатель автоматически оптимизирует это самостоятельно.

Я хочу вернуть ссылку на массив (который является свойством моего класса). Как PHP оптимизирует это, потому что массив не является объектом?

Если массив имеет 1 миллиард записей, не могу ли я получить два массива с 1 миллиардом записей, хранящихся в памяти, если я не передам его по ссылке?

ответ

5

PHP использует копию при записи. Это означает, что если вы передадите огромный массив в качестве параметра функции и только прочитаете его (например, foreach), вы не будете писать ему, поэтому ему не нужно делать копию.

$count = count($huge_array); // read the reference at the bottom 
for($i = 0; $i < $count $i++) { 
    $value = 2*$huge_array[$i]/15; 
    if($value > 3) 
     $sub_array []= $value; 
} 

в $ подмассив, который должен быть меньше (это подмножество огромного массива), будет содержать только необходимые (измененные) данные.

Если вы не собираетесь изменять значения исходного $ огромного_арра, он никогда не будет скопирован, поэтому дополнительная память не будет использоваться.

Если вы намерены изменить исходные значения массива, вам необходимо отправить , чтобы передать его по ссылке.

Если вы намереваетесь создавать и возвращать измененную версию исходного массива, то вы делаете нужной дополнительной памяти, которую PHP выделяет для вас.

Если вы планируете создавать и возвращать измененное меньшее подмножество исходного массива, то вы создадите новый пустой массив, в который вы скопируете некоторые данные из огромного массива и должны быть осторожны, чтобы не перезаписывать значения в $ Огромный_аррей, поэтому вы избегаете писать из $ large_array и подчеркиваете его чтение.

В этом link объясняется, что PHP был оптимизирован для использования в случаях использования по умолчанию.

Копирование на запись работает только в том случае, если переменная не является ссылкой, передаваемой функции, ожидающей значения, если она есть, передавая ее, вызывает триггер копии.

Это делает родные функции PHP, которые ожидали, что аргумент будет передан по значению и получит ссылочную переменную, скопируйте значение ссылки.

function foo(&$data) { 
    for ($i = 0; $i < strlen($data); $i++) { 
     do_something($data{$i}); 
    } 
} 

$string = "... looooong string with lots of data ....."; 
foo(string); 

Выполнение strlen в C подразумевает повторение всей строки для ее подсчета. В PHP строки имеют прикрепленное значение длины. Поэтому strlen возвращает значение, считанное оттуда (быстро).

Но если вы дадите ему ссылочную переменную, он должен будет скопировать его перед чтением его длины, чтобы он перебирал значение, чтобы скопировать его в список аргументов, прочитать и вернуть длину (и впоследствии освободить память для только что скопированная строка).

+0

Есть одна вещь. Foreach меняет массив: он меняет внутренний указатель массива. Поэтому COW здесь работать не будет. [Доказательство] (http://ideone.com/F2O3y) (foreach совпадает с параметром reset + next). – meze

+0

Вы уверены в этом? Я имею в виду, что я знаю, что это изменяет внутренний указатель, но делает ли это недействительным COW? –

+0

Я изменил свой ответ на цикл for с целым индексом. –

Смежные вопросы