TL; DR
а) метод / функція зчитує лише аргумент масиву => неявна (внутрішня) посилання
b) метод / функція змінює аргумент масиву => значення
в) аргумент масиву методу / функції явно позначений як посилання (з анкресом) => явна (користувальницька) посилання
Або це:
- параметр масиву без амперсанда : переданий посиланням; операції запису змінюють нову копію масиву, копія якої створюється при першому записі;
- параметр масиву ampersand : передається посиланням; операції запису змінюють вихідний масив.
Пам'ятайте - PHP робить копіює значення, коли ви пишете в параметр масиву без амперсанда. Ось що copy-on-write
означає. Я хотів би показати вам джерело С такої поведінки, але там страшно. Краще використовувати xdebug_debug_zval () .
Паскаль МАРТИН мав рацію. Коста Контос був ще більше.
Відповідь
Це залежить.
Довга версія
Я думаю, що я це записую для себе. Я повинен мати блог чи щось таке ...
Кожного разу, коли люди говорять про посилання (або вказівники, з цього приводу), вони зазвичай опиняються в логомачі (просто подивіться на цю тему !).
PHP, будучи поважною мовою, подумав, що мені слід додати плутанину (хоча це резюме вищезазначених відповідей). Тому що, хоча двоє людей можуть мати рацію одночасно, вам краще просто розбити голову разом в одну відповідь.
По-перше, ви повинні знати, що ви не педант, якщо не відповідаєте чорно-білим чином . Речі складніші, ніж "так / ні".
Як ви побачите, вся річ за значенням / за посиланням дуже пов'язана з тим, що саме ви робите з цим масивом у вашому методі / функції: читання чи модифікація?
Що говорить PHP? (він же "змін")
Керівництво каже , що це (курсив мій):
За замовчуванням аргументи функції передаються за значенням (так що якщо значення аргументу в межах функції буде змінено , воно не буде змінено поза функцією). Щоб функція могла змінювати свої аргументи, вони повинні бути передані посиланням .
Щоб аргумент функції, яка завжди передається посиланням, додайте амперсанд (&) до імені аргументу у визначенні функції
Наскільки я можу сказати, коли великі, серйозні, чесні до Бога програмісти говорять про посилання, вони зазвичай говорять про зміну значення цього посилання . І це саме те , що ручні переговори про: hey, if you want to CHANGE the value in a function, consider that PHP's doing "pass-by-value"
.
Однак є й інший випадок, який вони не згадують: що робити, якщо я нічого не зміню - просто прочитаю?
Що робити, якщо ви передаєте масив методу, який не позначає явно посилання, і ми не змінюємо цей масив в області функцій? Наприклад:
<?php
function readAndDoStuffWithAnArray($array)
{
return $array[0] + $array[1] + $array[2];
}
$x = array(1, 2, 3);
echo readAndDoStuffWithAnArray($x);
Читайте далі, мій попутник.
Що насправді робить PHP? (він же "пам'ять мудрий")
Ті ж великі і серйозні програмісти, коли вони стають ще серйознішими, вони говорять про "оптимізацію пам'яті" щодо посилань. Так само і PHP. Тому PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
що, ось чому .
Не було б ідеально передавати ОГРОМНІ масиви різним функціям, а PHP робити їх копії (саме це робить "pass-by-value").
<?php
// filling an array with 10000 elements of int 1
// let's say it grabs 3 mb from your RAM
$x = array_fill(0, 10000, 1);
// pass by value, right? RIGHT?
function readArray($arr) { // <-- a new symbol (variable) gets created here
echo count($arr); // let's just read the array
}
readArray($x);
Ну, якщо б це насправді було пропущеним значенням, у нас би залишилось 3 Мб + ОЗУ, тому що є дві копії цього масиву, правда?
Неправильно. Поки ми не змінюємо $arr
змінну, це посилання на пам'ять . Ви просто цього не бачите. Ось чому PHP згадує користувальницькі посилання під час розмови &$someVar
, щоб розрізняти внутрішні та явні (з амперсандом).
Факти
Так, when an array is passed as an argument to a method or function is it passed by reference?
Я придумав три (так, три) випадки:
а) метод / функція зчитує лише аргумент масиву
б) метод / функція змінює аргумент масиву
в) аргумент масиву методу / функції явно позначається як посилання (з ampersand)
По-перше, давайте подивимося, скільки пам’яті цей масив фактично їсть (запустіть тут ):
<?php
$start_memory = memory_get_usage();
$x = array_fill(0, 10000, 1);
echo memory_get_usage() - $start_memory; // 1331840
Та багато байтів. Чудово.
а) метод / функція зчитує лише аргумент масиву
Тепер давайте зробимо функцію, яка лише аргументує згаданий масив як аргумент, і ми побачимо, скільки пам'яті займає логіка читання:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
count($arr); // read
$x = $arr[0]; // read (+ minor assignment)
$arr[0] - $arr[1]; // read
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1); // this is 1331840 bytes
printUsedMemory($x);
Хочете здогадатися? Я отримую 80! Побачте самі . Це частина, яку опускає керівництво PHP. Якби $arr
параметр насправді був переданий за значенням, ви побачили б щось подібне до 1331840
байтів. Здається, що $arr
поводиться як довідник, чи не так? Це тому, що це посилання - внутрішнє.
б) метод / функція змінює аргумент масиву
Тепер напишемо до цього параму, а не читаємо з нього:
<?php
function printUsedMemory($arr)
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
Знову ж , подивитися на себе , але, для мене, це досить близько до 1331840. Так що в цьому випадку масив буде фактично скопійований в $arr
.
в) аргумент методу / функції явно позначений як посилання (з ампресом)
Тепер давайте подивимося, скільки пам’яті займає операція запису до явного посилання (запустіть тут ) - відмітьте амперсанд у підписі функції:
<?php
function printUsedMemory(&$arr) // <----- explicit, user-land, pass-by-reference
{
$start_memory = memory_get_usage();
$arr[0] = 1; // WRITE!
echo memory_get_usage() - $start_memory; // let's see the memory used whilst reading
}
$x = array_fill(0, 10000, 1);
printUsedMemory($x);
Моя обставина, ви отримуєте 200 макс! Таким чином, це з'їдає приблизно стільки ж пам’яті, скільки читання з параметри, що не належить до амперсанда .