Чи передаються змінні 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
Для передачі посилання означає, що ми можемо змінювати змінні, які бачать абонент. Який чітко код вище не робить. Нам потрібно змінити функцію 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
для того, щоб пройти посилання.
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
буде передаватися за значенням функції 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 року, в якій згадується це та інші відмінності OO між 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, але, наскільки я бачу, це стосується)
Другий принцип і джерело найбільш непорозумінь: Передача змінної функції виконується за замовчуванням як пропуск значення, тобто ви працюєте з копією. "Але об'єкти передаються за посиланням!" Поширена помилка як тут, так і в світі 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 - за посиланням.