Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Странности со ссылками на переменные

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
rgl
Отправлено: 11 Августа, 2017 - 13:17:18
Post Id



Новичок


Покинул форум
Сообщений всего: 56
Дата рег-ции: Авг. 2017  
Откуда: замкадье


Помог: 1 раз(а)




Новичком себя назвать не могу, но подходящего раздела не нашел, поэтому спрошу тут:

Есть массив, суть значений не важна, ну пусть для простоты будет 0,1,2 Вырезаю из этого массива кусок функцией array_slice(), теперь это мой кусок, и я могу в нем делать все, что хочу, на исходный массив это повлиять не должно. Ну пусть для простоты кусок будет всем массивом.

PHP:
скопировать код в буфер обмена
  1. $a = Array(0,1,2); # некий (чужой) массив
  2.  
  3. $my = array_slice( $a, 0 ); # вырезаю себе нужный кусочек, для простоты весь массив.
  4. # это моя копия, и я могу делать что хочу, в исходном все дожно остаться как было.
  5. # проверяем
  6. $my[1] = 'new';
  7. print_r($a);
  8. print_r($my);

Результат:
CODE (text):
скопировать код в буфер обмена
  1. X-Powered-By: PHP/5.3.13
  2. Content-type: text/html
  3.  
  4. Array
  5. (
  6.     [0] => 0
  7.     [1] => 1
  8.     [2] => 2
  9. )
  10. Array
  11. (
  12.     [0] => 0
  13.     [1] => new
  14.     [2] => 2
  15. )

т.е. я изменил что-то в своей копии, и исходного массива это не коснулось. А теперь подлянка - кто-то сдалал переменную-ссылку на элемент исходного массива. Теперь все стало не так:
PHP:
скопировать код в буфер обмена
  1. $a = Array(0,1,2); # некий (чужой) массив
  2. $t = &$a[1]; # на элемент этого массива есть ссылка, но я об этом не знаю, какое мое дело?
  3.  
  4. $my = array_slice( $a, 0 ); # вырезаю себе нужный кусочек, для простоты весь массив.
  5. # это моя копия, и я надеюсь что могу делать что хочу, в исходном все дожно остаться как было.
  6. # проверяем
  7. $my[1] = 'new';
  8. print_r($a);
  9. print_r($my);
  10.  

получаем:
CODE (text):
скопировать код в буфер обмена
  1. X-Powered-By: PHP/5.3.13
  2. Content-type: text/html
  3.  
  4. Array
  5. (
  6.     [0] => 0
  7.     [1] => new
  8.     [2] => 2
  9. )
  10. Array
  11. (
  12.     [0] => 0
  13.     [1] => new
  14.     [2] => 2
  15. )

Т.е. теперь значение поменялось в обоих массивах, хотя я не просил делать никаких ссылок. Это я что-то недопонимаю или ошибка в PHP?
 
 Top
Ch_chov
Отправлено: 11 Августа, 2017 - 14:36:09
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2121
Дата рег-ции: Июль 2008  
Откуда: из города


Помог: 90 раз(а)




Думаю, array_slice делает shallow copy, копирует данные вместе ссылками. Тоже самое происходит при клонировании объектов которые включаются в себя другие объекты. Даже clone $object не помогает.

(Отредактировано автором: 11 Августа, 2017 - 14:36:28)

 
 Top
Строитель Модератор
Отправлено: 11 Августа, 2017 - 14:36:25
Post Id



Участник


Покинул форум
Сообщений всего: 1580
Дата рег-ции: Февр. 2014  
Откуда: Украина


Помог: 73 раз(а)




А какой смысл в создании ссылки на ячейку массива? Если не ошибаюсь, ссылку создают на весь массив:
PHP:
скопировать код в буфер обмена
  1. $a = Array(0,1,2); # некий (чужой) массив
  2. $t = &$a;
И тогда результат обеих массивов вполне предсказуемый
PHP:
скопировать код в буфер обмена
  1. $my = array_slice( $a, 0 );
  2. $my[1] = 'new';
  3.  
  4. echo '<pre>'; var_dump($a, $my); echo '</pre>';
  5. /*
  6. array(3) {
  7.   [0]=>
  8.   int(0)
  9.   [1]=>
  10.   int(1)
  11.   [2]=>
  12.   int(2)
  13. }
  14. array(3) {
  15.   [0]=>
  16.   int(0)
  17.   [1]=>
  18.   string(3) "new"
  19.   [2]=>
  20.   int(2)
  21. }
  22. */
 
 Top
rgl
Отправлено: 16 Августа, 2017 - 15:40:53
Post Id



Новичок


Покинул форум
Сообщений всего: 56
Дата рег-ции: Авг. 2017  
Откуда: замкадье


Помог: 1 раз(а)




Строитель пишет:
А какой смысл в создании ссылки на ячейку массива? Если не ошибаюсь, ссылку создают на весь массив

Это может получиться случайно, напр. так:
PHP:
скопировать код в буфер обмена
  1. #X-Powered-By: PHP/5.3.13
  2.  
  3. $a = range('A','D');
  4.  
  5. # сейчас $a:
  6. # 'A','B','C','D'
  7.  
  8. foreach( $a as &$v )
  9.   $v = strtolower($v);
  10.  
  11. # теперь $a:
  12. # 'a','b','c','d'
  13.  
  14. #unset($v); # надо, но прикинемся что забыли
  15.  
  16. ###########################################
  17.  
  18. # ничего не подозревая делаем себе копию
  19. $b = array_slice( $a, 0 );
  20.  
  21. # меняем что-то в своей личной копии
  22. $b[3] = 'NEW';
  23.  
  24. echo $a[3];
  25. # в исходном массиве тоже поменялось :(
  26.  
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB