Переменные PHP передаются по значению или по ссылке?
Ответ 1
Согласно документации PHP, они передаются по значению.
По умолчанию аргументы функций передаются по значению (таким образом, если значение аргумента внутри функции изменяется, оно не изменяется за пределами функции). Чтобы функция могла изменять свои аргументы, они должны передаваться по ссылке.
Чтобы аргумент функции всегда передавался по ссылке, добавьте амперсанд (&) к имени аргумента в определении функции.
<?php
function add_some_extra(&$string) {
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // выводит 'This is a string, and something extra'.
?>
Ответ 2
В 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; //выведит 10
$y->changeValue($x);
echo $x->abc; //выведит 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; //выведит 10
$y->changeValue($x);
echo $x->abc; //выводит 10, а не 20, как это делает java.
А теперь посмотрите на это:
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; //выведит 10
$y->changeValue($x);
echo $x->abc; //выводы 20 невозможны в java.
Ответ 3
Похоже, многие люди путаются в том, как объекты передаются в функции и что означает передача по ссылке. Объект по-прежнему передается по значению, просто значение, которое передается в 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
Передача по ссылке означает, что мы можем изменять переменные, которые видит вызывающая сторона, чего явно не делает приведенный выше код. Нам нужно изменить функцию swap на:
<?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
Ответ 4
PHP поддерживает как передачу по значению, так и передачу по ссылке. Ссылки объявляются с помощью амперсанда (&); это очень похоже на то, как это делается в C++. Если формальный параметр функции не объявлен с амперсандом (т. е. не является ссылкой), все передается по значению, включая объекты. Нет никакого различия между тем, как передаются объекты и примитивы. Главное — понять, что передается, когда вы передаете объекты в функцию. Именно здесь понимание указателей имеет неоценимое значение. Для всех, кто столкнется с этим в будущем, я хочу поделиться этим замечанием из документации PHP, опубликованным анонимным пользователем:
Кажется, здесь есть некоторая путаница. Различие между указателями и ссылками не особенно полезно. Поведение в некоторых из уже опубликованных «исчерпывающих» примеров можно объяснить более простыми объединяющими терминами.
Первый принцип: Указатель хранит адрес памяти для доступа к объекту. Каждый раз, когда объекту присваивается адрес, создается указатель (я еще не слишком глубоко изучал движок Zend, но, насколько я могу судить, это именно так).
Второй принцип и источник наибольшей путаницы: Передача переменной в функцию по умолчанию выполняется как передача значения, т. е. вы работаете с копией. «Но объекты передаются по ссылке!» Распространенное заблуждение как здесь, так и в мире Java. Я никогда не говорил, что это копия ЧЕГО-ТО. По умолчанию передача осуществляется по значению. Всегда. Однако ЧТО копируется и передается, так это указатель. При использовании «->» вы, конечно, будете обращаться к тем же внутренним компонентам, что и исходная переменная в вызывающей функции. Простое использование «=» будет работать только с копиями.
Третий принцип:«&» автоматически и навсегда устанавливает имя другой переменной/указателя на тот же адрес памяти, что и что-то другое, пока вы не разъедините их. Здесь правильно использовать термин «псевдоним». Думайте об этом как о соединении двух указателей до тех пор, пока они не будут принудительно разделены с помощью «unset()». Эта функциональность существует как в одной области видимости, так и при передаче аргумента в функцию. Часто передаваемый аргумент называют «ссылкой», что связано с определенными различиями между «передачей по значению» и «передачей по ссылке», которые были более четкими в C и C++.
Просто помните: в функции передаются указатели на объекты, а не сами объекты. Эти указатели являются копиями оригиналов, если только вы не используете «&» в списке параметров для передачи оригиналов. Только когда вы разберетесь во внутреннем устройстве объекта, вы поймете, как все устроено.
А вот пример:
<?php
//Две переменные должны быть одним и тем же
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; // Теперь они разделят одну и ту же судьбу.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b разделяет значение $a
$b="Bizarro";
echo $a; // $a== "Кларк Кент" по-прежнему, так как $b теперь свободный агент-указатель.
//Эти два понятия НЕ являются одинаковыми.
$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;
//Вся эта работа исчезнет.
//потому что она была сделана на копиях указателей.
//Оригинальные указатели все еще указывают на оригиналы, как и раньше.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Обратите внимание на список параметров: теперь мы поменяли.
}
?>
Я написал обширный и подробный ответ, но я считаю, что он одинаково хорошо применим к PHP, C++ и любому другому языку, где люди, похоже, путаются в вопросах передачи по значению и передачи по ссылке.
Очевидно, что PHP, как и C++, является языком, который поддерживает передачу по ссылке. По умолчанию объекты передаются по значению. При работе с переменными, хранящими объекты, полезно рассматривать эти переменные как указатели (потому что это то, чем они являются на уровне ассемблера). Если вы передаете указатель по значению, вы все равно можете «отслеживать» указатель и изменять свойства объекта, на который он указывает. Что вы не можете сделать, так это заставить его указывать на другой объект. Только если вы явно объявите параметр как передаваемый по ссылке, вы сможете это сделать.
Ответ 5
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
Ответ 6Что касается того, как объекты передаются функциям, вам все еще нужно понять, что без «&» вы передаете функции хэндл объекта, который все еще передается по значению, и он содержит значение указателя. Но вы не можете изменить этот указатель, пока не передадите его по ссылке с помощью «&».
<?php
class Example {
public $value;
}
function test1($x) {
//let's say $x is 0x34313131
$x->value = 1; //будет отражаться за пределами этой функции
//php использует указатель 0x34313131 и ищет.
//адрес 'value' и изменяет его на 1
}
function test2($x) {
//$x is 0x34313131
$x = new Example;
//now $x is 0x88888888
//это НЕ будет отражаться за пределами этой функции
//вам нужно переписать это как "test2(&$x)".
$x->value = 1000; //это 1000 JUST внутри этой функции
}
$example = new Example;
$example->value = 0;
test1($example); // $example->value changed to 1
test2($example); // $example НЕ изменился на новый объект
// $example->value is still 1
?>
Ответ 7Ссылка в PHP — это псевдоним, позволяющий записывать в две разные переменные одно и то же значение. В PHP, если у вас есть переменная, которая содержит объект, эта переменная не содержит сам объект. Вместо этого она содержит идентификатор этого объекта. Ассистент объекта будет использовать идентификатор, чтобы найти реальный объект. Поэтому, когда мы используем объект в качестве аргумента в функции или присваиваем его другой переменной, мы копируем идентификатор, указывающий на сам объект.
class Type {}
$x = new Type();
$y = $x;
$y = "New value";
var_dump($x); // Выводит объект на печать.
var_dump($y); // Будет выведено "Новое значение"
$z = &$x; // $z является ссылкой на $x
$z = "New value";
var_dump($x); // Будет выведено "Новое значение"
var_dump($z); // Будет выведено "Новое значение"
Web