Переменные PHP передаются по значению или по ссылке?

Переменные PHP передаются по значению или по ссылке?

хорошее объяснение в codeexpertz.com/blog/php/…

Premlatha 02.04.2019 11:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
264
2
179 090
14
Перейти к ответу Данный вопрос помечен как решенный

Ответы 14

В зависимости от версии, 4 - по значению, 5 - по ссылке.

Я не думаю, что это правда.

Nick Heiner 18.08.2009 03:44

@ Карл Сегин, отчасти это правда. Раньше объекты PHP5 по умолчанию передавались по значению, но с 5 они передаются обработчиком, который на практике можно рассматривать как ссылку (с некоторыми исключениями), потому что мы можем изменять свойства объекта через них php.net/manual/en/language.oop5.references.php.

farynaio 28.04.2020 19:57

Переменные PHP назначаются по значению, передаются функциям по значению, а когда они содержат / представляют объекты, передаются по ссылке. Вы можете принудительно передать переменные по ссылке с помощью символа '&'.

Присваивается по значению / справочному примеру:

$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";

print ("var1: $var1, var2: $var2, var3: $var3);

выход:

var1: test, var2: final test, var3: final test

Передано по значению / справочному примеру:

$var1 = "foo";
$var2 = "bar";

changeThem($var1, $var2);

print "var1: $var1, var2: $var2";

function changeThem($var1, &$var2){
    $var1 = "FOO";
    $var2 = "BAR";
}

выход:

var1: foo, var2 BAR

Переменные объекта, переданные по справочному примеру:

class Foo{
    public $var1;

    function __construct(){
        $this->var1 = "foo";
    }

    public function printFoo(){
        print $this->var1;
    }
}


$foo = new Foo();

changeFoo($foo);

$foo->printFoo();

function changeFoo($foo){
    $foo->var1 = "FOO";
}

выход:

FOO

(Последний пример, наверное, мог бы быть лучше.)

«Объекты» не являются значениями в PHP5 и не могут быть «переданы». Значение $foo - указатель на объект. $foo - это передается по значению для функции changeFoo(), поскольку changeFoo() не объявлял свой параметр с &.

newacct 01.10.2013 04:03

@newacct Я думаю, вы имеете в виду, что указатель передается по значению, но также изменяется объект!

Achraf JEDAY 16.10.2020 16:18
Ответ принят как подходящий

Это по стоимости согласно Документация PHP.

By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.

To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}

$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>

У меня тоже было это сомнение (новичок) - так что, чтобы прояснить, это было бы то же самое, что и $str = add_some_extra($str);, если бы я не использовал ссылку, верно? тогда какова реальная добавленная стоимость этого?

Obmerk Kronen 24.11.2013 10:06

@Obmerk Если бы вы использовали нет, используя амперсанд для обозначения ссылкой, это не было бы эквивалентом. Обратите внимание, что функция не имеет оператора возврата, поэтому в вашем случае $str будет присвоено значение null.

The Unknown Dev 22.01.2015 22:31

если вы сделаете это таким образом @ObmerkKronen, вам придется вернуть значение и уловить его через свой код. В противном случае исходная переменная останется прежней.

Nabeel Khan 04.04.2016 23:54

Мне интересно, дает ли передача по ссылке некоторые преимущества в производительности или нет? Я передаю большой массив, и по умолчанию он передается по значению. Итак, если я использую вызов по ссылке, будет ли какое-то преимущество в производительности ??? (сохранение значений массива неизменными в течение всего процесса)

Choxx 08.10.2016 08:31

реальное преимущество состоит в том, что вы можете манипулировать / возвращать несколько значений. Вы также можете передавать переменные по ссылке и при этом позволять функции что-то возвращать.

Martin Schneider 18.06.2017 16:21

@Choxx Нет необходимости передавать массив по ссылке для повышения производительности. Механизм PHP использует копирование при записи - он физически не копирует массив пока не, он модифицируется в одной из областей, где он виден. Затем он делает копию, поэтому изменение применяется только в одном месте.

bdsl 04.12.2020 15:20

http://www.php.net/manual/en/migration5.oop.php

In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or passed as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).

Переменные, содержащие примитивные типы, в PHP5 передаются по значению. Переменные, содержащие объекты, передаются по ссылке. В Linux Journal от 2006 года есть довольно интересная статья, в которой упоминается это и другие объектно-ориентированные различия между 4 и 5.

http://www.linuxjournal.com/article/9170

Все переменные в PHP передаются по значению, если параметр функции не имеет &.

newacct 01.10.2013 04:03

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

<?php
class Holder {
    private $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return $this->value;
    }
}

function swap($x, $y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Выходы:

a, b

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

<?php
function swap(&$x, &$y) {
    $tmp = $x;
    $x = $y;
    $y = $tmp;
}

$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);

echo $a->getValue() . ", " . $b->getValue() . "\n";

Выходы:

b, a

для того, чтобы пройти по ссылке.

Я считаю это доказательство неверным. Похоже, вы пытались поменять местами ссылки. У вас проблема с назначением объектов. Вы переназначаете ссылку, которая является неизменной. Ценность, на которую он указывает, может быть изменена изнутри. Переопределение swap теперь передает ** x, что позволяет вам изменить * x. Проблема в том, чтобы думать, что $ x = $ y изменит то, на что изначально указывает $ x.

grantwparks 18.06.2012 00:26
Это не доказательство. The output of the first example is exactly what you'd expect if the current value of the entire object was passed to the swap function; in other words, if objects were "passed by value". On the other hand, it's also exactly what you'd expect if an object handle was passed to the function, which is actually what happens. Your code doesn't distinguish between these two cases.
EML 13.05.2015 00:58

Вы можете сделать это в любом случае.

Поместите символ '&' впереди, и переменная, которую вы передаете, станет той же самой, что и ее происхождение, то есть вы можете передавать по ссылке, а не делать ее копию.

так

    $fred = 5;
    $larry = & $fred;
    $larry = 8;
    echo $fred;//this will output 8, as larry and fred are now the same reference.

Это устарело и генерирует предупреждение

fijiaaron 25.02.2010 21:32

Объекты передаются по ссылке в PHP 5 и по значению в PHP 4. По умолчанию переменные передаются по значению!

Читайте здесь: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html

«Объекты» не являются значениями в PHP5 и не могут быть «переданы». Все переменные передаются по значению, если параметр переданной функции не имеет &.

newacct 01.10.2013 04:04

@newacct не совсем? Объекты - несколько передано по ссылке. Я думаю, что заметил, что объекты php могут быть изменены функциями, даже если они не определены с помощью & перед параметрами в определении - если они были переданы по значению, объект, содержащийся в области, который вызывал функцию с ним в качестве параметра не пострадает.

Félix Gagnon-Grenier 21.12.2014 13:24

@ FélixGagnon-Grenier: Опять же, «объекты» не являются значениями и не могут быть «переданы». У вас не может быть «переменной» в PHP5, значение которой является «объектом», вы можете иметь только значение, которое является ссылкой на объект (то есть указателем на объект). Конечно, вы можете передать или назначить указатель на объект по значению и изменить объект, на который он указывает, вызвав метод, который выполняет такое изменение. Это не имеет ничего общего с передачей по ссылке. Какой тип имеет значение и является ли параметр передачей по значению / передачей по ссылке, - это независимые и ортогональные вещи.

newacct 21.12.2014 13:28

class Holder
{
    private $value;

    public function __construct( $value )
    {
        $this->value = $value;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function setValue( $value )
    {
        return $this->value = $value;
    }
}

class Swap
{       
    public function SwapObjects( Holder $x, Holder $y )
    {
        $tmp = $x;

        $x = $y;

        $y = $tmp;
    }

    public function SwapValues( Holder $x, Holder $y )
    {
        $tmp = $x->getValue();

        $x->setValue($y->getValue());

        $y->setValue($tmp);
    }
}


$a1 = new Holder('a');

$b1 = new Holder('b');



$a2 = new Holder('a');

$b2 = new Holder('b');


Swap::SwapValues($a1, $b1);

Swap::SwapObjects($a2, $b2);



echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";

echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";

Атрибуты можно изменять, если они не переданы по ссылке, так что будьте осторожны.

Выход:

SwapObjects: b, a SwapValues: a, b

В PHP по умолчанию объекты передаются как ссылка на новый объект.

См. Этот пример:

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
   $obj->abc = 30;
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30

Теперь посмотрим на это:

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue($obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.

Теперь посмотрим на это:

class X {
  var $abc = 10; 
}

class Y {

  var $abc = 20; 
  function changeValue(&$obj)
  {
    $obj = new Y();
  }
}

$x = new X();
$y = new Y();

echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.

Надеюсь, вы понимаете это.

Это очень хорошо иллюстрирует, как работает объект PHP.

Frederik Krautwald 01.11.2014 12:56

1-й пример, значение ссылки obj передается в функцию, изменения в obj с использованием новой ссылки будут отражаться на всех других ссылках, указывающих на тот же объект obj. 2-й пример, снова ЗНАЧЕНИЕ ссылки на объект передается функции, функция изменяет значение ссылки, чтобы указать на новый объект, старый объект остается прежним. 3-й пример, ссылка на значение ссылки obj передается в функцию, таким образом, изменения в функции работают с одним и тем же объектом obj.

s-hunter 28.04.2015 05:26

Прекрасные примеры и именно то, что я думал, что произойдет. Я новичок в PHP (из фона Javascript / node.js), и иногда трудно понять, что происходит, но это очень ясно!

TKoL 13.05.2019 13:26

Этот пример излишне сложен. $y не нужен - в function changeValue нет ничего, что требовало бы, чтобы он находился внутри class Y, так что это переплетает две несвязанные концепции. Я бы переместил function changeValue во внешний прицел, чуть выше $x = new X();. Удалите все ссылки на $y. Теперь легче увидеть, что первые два примера оставляют $ x в покое, а третий изменяет свое содержимое на new Y(). Что было бы легче увидеть, если бы вы сбросили type из $x - тот факт, что и X, и Y включают поле $abc, также не имеет отношения к тому, что демонстрируется.

ToolmakerSteve 02.07.2019 02:22

Вы можете передать переменную функции по ссылке. Эта функция сможет изменять исходную переменную.

Вы можете определить отрывок по ссылке в определении функции:

<?php
function changeValue(&$var)
{
    $var++;
}

$result=5;
changeValue($result);

echo $result; // $result is 6 here
?>

На самом деле действительны оба метода, но это зависит от ваших требований. Передача значений по ссылке часто замедляет ваш скрипт. Так что лучше передавать переменные по значению с учетом времени выполнения. Кроме того, поток кода более согласован, когда вы передаете переменные по значению.

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

function add(&$var){ // The &amp; is before the argument $var
   $var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced

TL; DR: PHP поддерживает как передачу по значению, так и передачу по ссылке. Ссылки объявляются с использованием амперсанда (&); это очень похоже на то, как это делает C++. Когда формальный параметр функции не объявлен с амперсандом (т.е. это не ссылка), все передается по значению, включая объекты. Нет различия между тем, как передаются объекты и примитивы. Ключ в том, чтобы понять, что Какие передается, когда вы передаете объекты в функцию. Здесь бесценно понимание указателей.

Для всех, кто столкнется с этим в будущем, я хочу поделиться этой жемчужиной из Документы PHP, опубликованные анонимным пользователем:

There seems to be some confusion here. The distinction between pointers and references is not particularly helpful. The behavior in some of the "comprehensive" examples already posted can be explained in simpler unifying terms. Hayley's code, for example, is doing EXACTLY what you should expect it should. (Using >= 5.3)

First principle: A pointer stores a memory address to access an object. Any time an object is assigned, a pointer is generated. (I haven't delved TOO deeply into the Zend engine yet, but as far as I can see, this applies)

2nd principle, and source of the most confusion: Passing a variable to a function is done by default as a value pass, ie, you are working with a copy. "But objects are passed by reference!" A common misconception both here and in the Java world. I never said a copy OF WHAT. The default passing is done by value. Always. WHAT is being copied and passed, however, is the pointer. When using the "->", you will of course be accessing the same internals as the original variable in the caller function. Just using " = " will only play with copies.

3rd principle: "&" automatically and permanently sets another variable name/pointer to the same memory address as something else until you decouple them. It is correct to use the term "alias" here. Think of it as joining two pointers at the hip until forcibly separated with "unset()". This functionality exists both in the same scope and when an argument is passed to a function. Often the passed argument is called a "reference," due to certain distinctions between "passing by value" and "passing by reference" that were clearer in C and C++.

Just remember: pointers to objects, not objects themselves, are passed to functions. These pointers are COPIES of the original unless you use "&" in your parameter list to actually pass the originals. Only when you dig into the internals of an object will the originals change.

И вот пример, который они предоставляют:

<?php

//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.

$b = "Superman"; // $a= = "Superman" too.
echo $a;
echo $a = "Clark Kent"; // $b= = "Clark Kent" too.
unset($b); // $b divorced from $a
$b = "Bizarro";
echo $a; // $a= = "Clark Kent" still, since $b is a free agent pointer now.

//The two are NOT meant to be the same.
$c = "King";
$d = "Pretender to the Throne";
echo $c."\n"; // $c= = "King"
echo $d."\n"; // $d= = "Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c= = "King"
echo $d."\n"; // $d= = "Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c= = "Pretender to the Throne"
echo $d."\n"; // $d= = "King"

function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}

function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}

?>

Я написал обширное подробное сообщение в блоге на эту тему для JavaScript., но я считаю, что он одинаково хорошо применим к PHP, C++ и любому другому языку, где люди, кажется, не понимают, что такое передача по значению или передача по ссылке.

Ясно, что PHP, как и C++, - это язык, который поддерживает передачу по ссылке. По умолчанию объекты передаются по значению. При работе с переменными, в которых хранятся объекты, полезно видеть эти переменные как указатели (потому что это, по сути, то, чем они являются на уровне сборки). Если вы передаете указатель по значению, вы все равно можете «отслеживать» указатель и изменять свойства объекта, на который он указывает. Чего вы не можете сделать, так это указать ему на другой объект. Только если вы явно объявите параметр как передаваемый по ссылке, вы сможете это сделать.

Это должно быть добавлено в начало и заблокировано от редактирования.

fearis 10.03.2021 14:33

Другие вопросы по теме