1) Когда массив передается в качестве аргумента методу или функции, передается ли он по ссылке или по значению?
2) При назначении массива переменной, новая переменная является ссылкой на исходный массив, или это новая копия?
Как насчет этого:
$a = array(1,2,3);
$b = $a;
Является ли $b
ссылка $a
?
Ответы:
Вторую часть вашего вопроса смотрите на странице массива руководства , в которой говорится (цитирование) :
И приведенный пример:
Для первой части лучший способ убедиться в этом - попробовать ;-)
Рассмотрим этот пример кода:
Это даст такой вывод:
Что указывает на то, что функция не изменила «внешний» массив, который был передан в качестве параметра: он передается как копия, а не как ссылка.
Если вы хотите, чтобы он передавался по ссылке, вам придется изменить функцию следующим образом:
И на выходе получится:
Как, на этот раз, массив был передан «по ссылке».
Не стесняйтесь читать раздел руководства « Объяснение литературы» : он должен ответить на некоторые ваши вопросы ;-)
источник
&
, да, это должно - см. Php.net/manual/en/…Что касается вашего первого вопроса, массив передается по ссылке, ЕСЛИ он не изменен в вызываемом вами методе / функции. Если вы пытаетесь изменить массив в методе / функции, сначала создается его копия, а затем изменяется только копия. Это создает впечатление, что массив передается по значению, хотя на самом деле это не так.
Например, в этом первом случае, даже если вы не определяете, что ваша функция принимает $ my_array по ссылке (используя символ & в определении параметра), она все равно передается по ссылке (т.е. вы не тратите память с ненужной копией).
Однако, если вы модифицируете массив, сначала делается его копия (который использует больше памяти, но оставляет исходный массив без изменений).
К вашему сведению - это называется «ленивым копированием» или «копированием при записи».
источник
TL; DR
a) метод / функция читает только аргумент массива => неявная (внутренняя) ссылка
b) метод / функция изменяет аргумент массива => значение
c) аргумент массива метода / функции явно помечается как ссылка (с амперсандом) => явная (пользовательская) ссылка
Или это:
- параметр массива без амперсанда : передается по ссылке; операции записи изменяют новую копию массива, копия которой создается при первой записи;
- параметр массива амперсанд : передается по ссылке; Операции записи изменяют исходный массив.
Помните - PHP копирует значение в тот момент, когда вы записываете в параметр non-ampersand array. Вот что
copy-on-write
значит. Я хотел бы показать вам источник C этого поведения, но там страшно. Лучше использовать 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? (иначе "по памяти")
Те же крупные и серьезные программисты, когда они становятся еще более серьезными, говорят об «оптимизации памяти» в отношении ссылок. Как и PHP. Потому
PHP is a dynamic, loosely typed language, that uses copy-on-write and reference counting
что вот почему .Было бы не идеальным передавать массивы HUGE различным функциям, а PHP делать их копии (в конце концов, именно это и делает «передача по значению»):
Ну, а теперь, если бы это на самом деле было передачей по значению, у нас бы ушло около 3 Мб + ОЗУ, потому что есть две копии этого массива, верно?
Неправильно. Пока мы не меняем
$arr
переменную, это ссылка для памяти . Вы просто не видите этого. Вот почему PHP упоминает пользователь землю ссылку , когда речь идет о&$someVar
, чтобы различать внутренние и явные (с амперсандом) из них.факты
Так,
when an array is passed as an argument to a method or function is it passed by reference?
Я придумал три (да, три) случая:
а) метод / функция читает только аргумент массива
б) метод / функция модифицирует аргумент массива
в) аргумент массива метода / функции явно помечается как ссылка (с амперсанд)
Во-первых, давайте посмотрим, сколько памяти фактически использует этот массив (запустите здесь ):
Это много байтов. Отлично.
а) метод / функция читает только аргумент массива
Теперь давайте создадим функцию, которая только читает указанный массив в качестве аргумента, и посмотрим, сколько памяти занимает логика чтения:
Хотите догадаться? Я получаю 80! Смотрите сами . Это часть, которую руководство по PHP опускает. Если бы
$arr
параметр был фактически передан по значению, вы бы увидели нечто похожее на1331840
байты. Кажется, что$arr
ведет себя как ссылка, не так ли? Это потому , что это а ссылки - внутренний один.б) метод / функция изменяет аргумент массива
Теперь давайте напишем в этот параметр вместо чтения из него:
Опять же , посмотреть на себя , но, для меня, это довольно близко к 1331840. Так что в этом случае массив будет фактически скопирован в
$arr
.c) аргумент массива метода / функции явно помечен как ссылка (с амперсандом)
Теперь давайте посмотрим, сколько памяти занимает операция записи в явную ссылку (запустите здесь ) - обратите внимание на амперсанд в сигнатуре функции:
Моя ставка в том, что вы получите 200 макс! Так что это съедает примерно столько же памяти, сколько и чтение из параметра без амперсанда .
источник
По умолчанию
Массивы объектов передаются по значению (массиву), но каждый объект передается по ссылке.
Примечание. В качестве оптимизации каждое отдельное значение передается как ссылка, пока оно не будет изменено внутри функции. Если оно было изменено и значение было передано по ссылке, оно копируется и копия изменяется.
источник
Когда массив передается методу или функции в PHP, он передается по значению, если вы явно не передаете его по ссылке, например:
Во втором вопросе речь
$b
идет не о ссылке$a
, а о$a
.Как и в первом примере, вы можете ссылаться
$a
, выполнив следующее:источник
Эта ветка немного старше, но вот кое-что, с чем я только что столкнулся:
Попробуйте этот код:
http://codepad.viper-7.com/gwPYMw
Обратите внимание, что для параметра $ params нет усилителя, и все же он меняет значение $ arr ['date']. Это не совсем соответствует всем другим объяснениям здесь и тому, что я думал до сих пор.
Если я клонирую объект $ params ['date'], вторая выходная дата остается прежней. Если я просто установлю его в строку, это не повлияет на вывод.
источник
Чтобы расширить один из ответов, также подмассивы многомерных массивов передаются по значению, если явно не переданы по ссылке.
Результат:
источник
В PHP массивы по умолчанию передаются в функции по значению, если вы явно не передаете их по ссылке, как показано в следующем фрагменте:
Вот вывод:
источник