Переменные PHP передаются по значению или по ссылке?
Переменные PHP передаются по значению или по ссылке?
Ответы:
Это по стоимости в соответствии с документацией PHP .
По умолчанию аргументы функции передаются по значению (поэтому, если значение аргумента в функции изменяется, оно не изменяется вне функции). Чтобы позволить функции изменять свои аргументы, они должны быть переданы по ссылке.
Чтобы аргумент функции всегда передавался по ссылке, добавьте амперсанд ( & ) к имени аргумента в определении функции.
<?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);
если бы я не использовал ссылку, верно? тогда какова реальная добавленная стоимость этого?
$str
в вашем случае ей будет присвоен ноль.
В 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.
Я надеюсь, что вы можете понять это.
$y
в этом нет необходимости - нет ничего, function changeValue
что требовало бы, чтобы оно было внутри class Y
, чтобы объединить два не связанных между собой понятия. Я бы переместился function changeValue
во внешнюю сферу, чуть выше $x = new X();
. Удалить все ссылки на $y
. Теперь легче увидеть, что первые два примера оставляют $ x в покое, а третий меняет свое содержимое на new Y()
. Какой бы легче увидеть , если вы выбросили type
из $x
- за того , что , как X
и Y
случается, включают в себя $abc
поле также не имеет отношения к тому , что показано
Кажется, многие люди смущаются тем, как объекты передаются в функции и что означает передача по ссылке. Переменные объекта по-прежнему передаются по значению, просто значение, которое передается в 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
функции; другими словами, если объекты были «переданы по значению». С другой стороны, это именно то, что вы ожидаете, если дескриптор объекта будет передан функции, что на самом деле и происходит. Ваш код не различает эти два случая.
http://www.php.net/manual/en/migration5.oop.php
В PHP 5 появилась новая объектная модель. Обработка объектов в PHP была полностью переписана, что позволило повысить производительность и расширить возможности. В предыдущих версиях PHP объекты обрабатывались как примитивные типы (например, целые числа и строки). Недостатком этого метода было то, что семантически весь объект копировался при присвоении переменной или передавался в качестве параметра методу. В новом подходе на объекты ссылаются по дескриптору, а не по значению (можно рассматривать дескриптор как идентификатор объекта).
Переменные PHP присваиваются по значению, передаются в функции по значению, а когда содержат / представляют объекты, передаются по ссылке. Вы можете принудительно передать переменные по ссылке, используя &
Назначено по значению / справочному примеру:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
будет выводить
var1: тест, var2: финальный тест, var3: финальный тест
Передано по стоимости / справочный экзамен:
$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
(последний пример мог бы быть лучше ...)
$foo
является указателем на объект . $foo
будет передаваться по значению функции changeFoo()
, а changeFoo()
не объявить его параметр с &
.
Вы можете сделать это в любом случае.
поместите символ «&» перед собой, и переменная, которую вы передаете, становится такой же, как и ее источник. То есть: вы можете передать по ссылке, а не сделать его копию.
так
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
Переменные, содержащие примитивные типы, передаются по значению в PHP5. Переменные, содержащие объекты, передаются по ссылке. В Linux Journal от 2006 года есть довольно интересная статья, в которой упоминается это и другие различия между 4 и 5.
&
.
Объекты передаются по ссылке в PHP 5 и по значению в PHP 4. Переменные по умолчанию передаются по значению!
Читайте здесь: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
&
.
&
перед параметрами в определении - если они были переданы по значению, объект, содержащийся в области видимости, который вызвал функцию с этим параметром, не быть затронутым.
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, опубликованных анонимным пользователем :
Кажется, здесь есть некоторая путаница. Различие между указателями и ссылками не особенно полезно. Поведение в некоторых уже опубликованных «всеобъемлющих» примерах можно объяснить более простыми объединяющими терминами. Например, код Хейли делает именно то, что и следовало ожидать. (Используя> = 5.3)
Первый принцип: указатель хранит адрес памяти для доступа к объекту. Каждый раз, когда объект назначается, создается указатель. (Я еще не углубился в движок Zend, но, насколько я понимаю, это применимо)
2-й принцип и источник наибольшей путаницы: передача переменной в функцию выполняется по умолчанию как передача значения, т. Е. Вы работаете с копией. «Но объекты передаются по ссылке!» Распространенное заблуждение как здесь, так и в мире Java. Я никогда не говорил копию ЧТО. Передача по умолчанию выполняется по значению. Всегда. То, что копируется и передается, однако, является указателем. Используя «->», вы, конечно, будете получать доступ к тем же внутренним элементам, что и исходная переменная в функции вызывающей стороны. Просто используя «=» будет играть только с копиями.
Третий принцип: «&» автоматически и навсегда устанавливает другое имя переменной / указатель на тот же адрес памяти, что и другие, до тех пор, пока вы не отделите их. Здесь правильно использовать термин «псевдоним». Думайте об этом как о соединении двух указателей на бедре, пока они не будут принудительно разделены с помощью "unset ()". Эта функциональность существует как в одной и той же области видимости, так и при передаче аргумента в функцию. Часто передаваемый аргумент называется «ссылкой» из-за определенных различий между «передачей по значению» и «передачей по ссылке», которые были более понятными в C и C ++.
Просто помните: указатели на объекты, а не сами объекты, передаются функциям. Эти указатели являются КОПИЯМИ оригинала, если вы не используете «&» в своем списке параметров для фактической передачи оригиналов. Только когда вы копаете внутренности объекта, оригиналы изменятся.
И вот пример, который они предоставляют:
<?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 ++, является языком, который поддерживает передачу по ссылке. По умолчанию объекты передаются по значению. При работе с переменными, которые хранят объекты, это помогает видеть эти переменные как указатели (потому что это на самом деле то, чем они являются на уровне сборки). Если вы передаете указатель по значению, вы все равно можете «проследить» указатель и изменить свойства объекта, на который указывает указатель. То, что вы не можете сделать, это указать на другой объект. Только если вы явно объявите параметр как переданный по ссылке, вы сможете сделать это.
На самом деле оба метода действительны, но это зависит от ваших требований. Передача значений по ссылке часто замедляет выполнение сценария. Поэтому лучше передавать переменные по значению, учитывая время выполнения. Кроме того, поток кода более согласован, когда вы передаете переменные по значению.
Используйте это для функций, когда вы хотите просто изменить исходную переменную и вернуть ее снова к тому же имени переменной с назначенным ей новым значением.
function add(&$var){ // The & 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
Зависит от версии, 4 по значению, 5 по ссылке.