PHP &ссылка

Ragnarok
На сайте с 25.06.2010
Offline
239
599

Пробую сделать такую штуку:

$ar = array(1,2,3);
foreach ($ar as $a) {
$a+=1;
}
VAR_DUMP($ar);

Получаю


array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}

всё правильно. теперь, добавляю & в foreach

$ar = array(1,2,3);
foreach ($ar as &$a) {
$a+=1;
}
VAR_DUMP($ar);


array(3) {
[0]=>
int(2)
[1]=>
int(3)
[2]=>
&int(4)
}

и всё тоже правильно, но откуда взялась & у последнего элемента?

[2]=>
&int(4)
//TODO: перестать откладывать на потом
LEOnidUKG
На сайте с 25.11.2006
Offline
1742
#1

Значит так надо. А какая разница то?

делаем print_r, всё нормально в элементах:

Array ( [0] => 2 [1] => 3 [2] => 4 )

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/ ✅ Настройка и оптимизация серверов https://getmanyspeed.ru/
Оптимизайка
На сайте с 11.03.2012
Offline
396
#2
Ragnarok:
но откуда взялась & у последнего элемента?

Какой то баг php что-ли? Нет такого:

$ php test.php

array(3) {

[0] =>

int(2)

[1] =>

int(3)

[2] =>

int(4)

}

$ php -v

PHP 5.5.9-1ubuntu4.11 (cli) (built: Jul 2 2015 15:23:08)

Copyright (c) 1997-2014 The PHP Group

Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies

with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies

with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans

⭐ BotGuard (https://botguard.net) ⭐ — защита вашего сайта от вредоносных ботов, воровства контента, клонирования, спама и хакерских атак!
Ragnarok
На сайте с 25.06.2010
Offline
239
#3
LEOnidUKG:
А какая разница то?

для общего развития и понимания тонкостей. ещё пример

$arr = $new = array();

$arr[] = &$new;

$new['name'] = "Абырвалг";
$new['phone'] = 123456;

$arr[] = $new;

VAR_DUMP($arr);

и оп

array(2) {
[0]=>
&array(2) {
["name"]=>
string(16) "Абырвалг"
["phone"]=>
int(123456)
}
[1]=>
array(2) {
["name"]=>
string(16) "Абырвалг"
["phone"]=>
int(123456)
}
}


---------- Добавлено 06.08.2015 в 18:37 ----------

Оптимизайка,

$ php5 -v

PHP 5.5.26-1+deb.sury.org~precise+1 (cli) (built: Jun 15 2015 10:04:48)

Copyright (c) 1997-2015 The PHP Group

Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies

with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

проверил ещё на

# php -v

PHP 5.4.43 (cli) (built: Jul 13 2015 12:26:16)

та же ерунда)

PN
На сайте с 22.08.2012
Offline
103
#4

А если так?

$ar = array(1,2,3);

foreach ($ar as &$a) {
$a+=1;
}
unset($a);
VAR_DUMP($ar);
Мой совет помог? Не скупись! Bitcoin 1Lseddet1o1B6odgXQHbGaWGwRkt1Db8Ef Ethereum 0x450f1a17461e25194B7F9226cDEe70173F39e1e1
K
На сайте с 03.06.2015
Offline
45
#5
Ragnarok:
но откуда взялась & у последнего элемента

Оттуда что после таких форичей принято делать вот так

unset($a);

Else if эта переменная будет использована ниже по коду и все что в нее попадет - окажется в последнем элементе того самого саррая.

---------- Добавлено 06.08.2015 в 18:46 ----------

proksey-net:
А если так?

Не видел, именно оно самое.

---------- Добавлено 06.08.2015 в 18:55 ----------

Как вы пишите для общего развития: в php (а равно в js) конструкции языка типа for, switch, foreach, if, else и тп - не образуют блочного scope, то есть все задействованные внутри конструкции переменные оказываются в текущем контексте. Если в переменной значение, то ее можно реюзать, а если реф - тоже можно, если знать зачем, а если незачем, на всякий пожарный лучшее ее выпилить с дерева. Как вариант если немного входящих, то заворачиваем в безымянную функцию


$foreach = function(&$arr){
foreach($arr as &$a)
$a+=1;
};
$foreach($bar);


---------- Добавлено 06.08.2015 в 19:01 ----------

Еще для общего. В теории указатели (которые ссылки) служат для снижения расхода памяти на копирование значений, типа передает адрес и оперируем тем, что по этому адресу находится. Так вот php - это не язык и творцы клянутся что рефы фактически не нужны, что, типа, интерпретатор и сам все зашибись оптимизирует и волноваться не о чем. Я не проверял и юзаю рефы всегда когда есть смысл.

Кстати рефы на объекты это отдельный лимерик.

---------- Добавлено 06.08.2015 в 19:09 ----------

Ragnarok:
та же ерунда)

Академик открыл для себя указатели, называется. :)

Так и должно быть. В элементе 0 - реф на массив, а в элементе 1 - копия того же массива.

Практический смысл?

Я тут постил одному человеку функцию echoit, она красивее выводит в браузер:


Array
(
[0] => Array
(
[name] => FooBarBaz
[phone] => 123456
)

[1] => Array
(
[name] => FooBarBaz
[phone] => 123456
)

)


---------- Добавлено 06.08.2015 в 19:18 ----------

Практический смысл можно найти например в передаче адреса элемента в большом и сложном массиве, или сделать шорткат $o=&$this->opts; для местного применения, или как в вашем первом примере поменять все значения не отходя от кассы, или передать ссылку на функцию ей же самой, например:


$foo = function() use(&$foo){
};

без чего рекурсия с кложой не будет работать. Утомил? Отдыхайте :)

MYSQL PHP JS HTML CSS SEO TXT США СССР
SocFishing
На сайте с 26.09.2013
Offline
118
#6
Ragnarok:

всё правильно. теперь, добавляю & в foreach

Для того, чтобы напрямую изменять элементы массива внутри цикла, переменной $a должен предшествовать знак &. В этом случае значение будет присвоено по ссылке.

<?php
$ar = array(1,2,3);
foreach ($ar as &$a) {
$a+=1;
}
unset($a);
VAR_DUMP($ar);
<?php
$ar = array(1,2,3);
$b = 0;
foreach ($ar as $a) {
$ar[$b]++;
$b++;
}
VAR_DUMP($ar);
★Сервис идентифицирует (https://socfishing.com/?utm_source=searchengines) посетителей вашего сайта и предоставляет их профили ВКонтакте, Телефон, Почта! Цены копеечные, работаем 8 лет.
K
На сайте с 03.06.2015
Offline
45
#7
SocFishing:
Для того, чтобы напрямую

Вот как "напрямую", прямее некуда:


$ar=array(1,2,3,);
foreach($ar as $i=>$v)
$ar[$i]=1+$v;

"Ссылки", которые указатели, в точности наоборот обращаются не напрямую, а через адрес данных в выделенной памяти. То есть накривую, кривее некуда.

---------- Добавлено 07.08.2015 в 07:40 ----------

Кстати народ часто задает вопрос как удалить элемент массива в конструкции foreach. Попытка удалить реф сами понимаете ничего не даст. Удалится сам реф, а не то, на что он указывал, а в следующей итерации реф заново будет создан.

Удалить можно только напрямую:


$ar=array(1,2,3,);
foreach($ar as $i=>$v) {
if($i==1)
unset($ar[$i]);
else
$ar[$i]=1+$v;
}

Теперь должно быть вполне понятно что такое напрямую.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий