За последние 24 часа нас посетили 56993 программиста и 1694 робота. Сейчас ищет 881 программист ...

Ссылки на элементы массива (советую всем прочитать)

Тема в разделе "Прочие вопросы по PHP", создана пользователем karlozzz, 6 дек 2010.

  1. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    Оказывается, если мы ссылаемся на элемент массива, то php выносит этот объект отдельно от массива, а в массиве ставит ссылку на него, также как и в текущем объекте, например данный код будет работать не так, как планировалось изначально

    PHP:
    1.  
    2. <?php
    3. $a = array('qw', array('as', 'as'));
    4. $b = &$a[1];
    5. $c = $a;
    6. echo '<br>';
    7. unset($c[1][1]);
    8.  
    Посмотрите, интересный нюанс, сам очень долго искал ошибку (конечно в другом коде, это лишь демонстрация), теперь вот проверяю все, боюсь как бы в других местах подобная хрень не вылезла
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Мдя, странное поведение
     
  3. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    Вот что нашел еще к теме

    Баг решено не исправлять, а задокументировать
    http://bugs.php.net/bug.php?id=20993

    Глупость, такой маразм, подобные вещи нужно считать тем - чем они являются, это баг, он нарушает работу логически верной программы
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    баг, спорить не о чем. ну да фик с ним. =)
     
  5. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    И да, лечиться например так

    PHP:
    1.  
    2.  
    Ну разве не глупость
     
  6. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    для тех кому влом проверять php 5.3.3:
    PHP:
    1. <?php
    2. $a = array('qw', array('as', 'as'));
    3. $b = &$a[1];
    4. $c = $a;
    5. echo '<br>';
    6. unset($c[1][1]);
    7.  
    без ссылки

    PHP:
    1. <?php
    2. $a = array('qw', array('as', 'as'));
    3. //$b = &$a[1];
    4. $c = $a;
    5. echo '<br>';
    6. unset($c[1][1]);
    karlozzz и в чём отсутствие логики расскажи?
     
  7. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
     
  8. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    да, согласен, фигня выходит.... Но впринципе как связанность массивов это фича, но она какая то дибильная...
     
  9. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    у меня со второй и без второй строки результаты отличаются. кто-то хочет сказать, что так и должно быть?
     
  10. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    Если мне надо будет сделать так, я сам сделаю, а я хочу именно ссылку на элемент массива, а интерпретатор какую то ху*** делает
     
  11. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    igordata
    Читай выше, в этом и баг
     
  12. alBoo

    alBoo Активный пользователь

    С нами с:
    27 мар 2008
    Сообщения:
    63
    Симпатии:
    0
    Вполне адекватное поведение
    Сначала создается статичная переменная $a типа массив
    При обращении к ней как к ссылке вся переменная $a становится ссылкой на массив, $b - ссылка на часть массива (массив - кусок памяти, ссылки на него - переменная с адресом этой памяти)
    $c = $a - создается еще одна ссылка на этот же массив
    unset($c[1][1]);
    удаляется часть массива по ссылке

    по сути, просто неявное преобразование типов
     
  13. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    С чего бы вдруг?
    Глупость, $c копия $a

    Дело то в том, что когда мы пытаемся сослаться на массив
    $b = &$a[1];
    Тогда происходит примерно такое (что по логике происходить не должно)

    $tmp = $a[1];
    $a[1] = &$tmp;
    $b = &$tmp;

    Поэтому когда мы копируем массив
    $c = $a
    Массив копируется нормально, но подмассива $a[1] не существует, в нем хранится ссылка на $tmp (некую область памяти), что я считаю не верными действиями интерпретатора, конечно самый простой вариант не исправлять баг, а задокументировать его...
     
  14. alBoo

    alBoo Активный пользователь

    С нами с:
    27 мар 2008
    Сообщения:
    63
    Симпатии:
    0
    с того, что изначально была переменная, отдельная, статичная, и тут понадобилось сделать ссылку на часть этой переменной.
    соотв. массив разворачивается как отдельная сущность в памяти, $a указывает на начало сегмента памяти, $b на другой участок этой памяти
    Если бы в PHP массивы сразу бы представлялись ссылками на сегмент памяти (как в C), я думаю таких недоразумений не было бы)

    глупость не читать мануалы
    при $c = $a - создается ссылка на $a до тех пор пока над $c не производили никаких действий (php>5.0), т.е. значение из $a скопируется напр только после $c = $c + 1; (зы. объекты всегда передаются по ссылке)
    но поскольку $a = ссылка на массив, то $c автоматически тоже становится ссылкой на массив

    простой пример
    PHP:
    1.  
    2. <?php
    3. echo 'START: ' . memory_get_usage() . PHP_EOL;
    4. $a = array('a', 'xcv', 'ertc', 'dttre', 'cxc', 'r6y', '234');
    5. echo 'CREATED $a: ' . memory_get_usage() . PHP_EOL; // array size - 1 488b
    6. $b = $a;
    7. echo 'CREATED $b: ' . memory_get_usage() . PHP_EOL; // link size - 96b
    8. $b[] = 'x';
    9. echo 'MODIFIED $b: ' . memory_get_usage() . PHP_EOL; // new array size - 1 024b + 96b = 1 120b
    10.  
     
  15. alBoo

    alBoo Активный пользователь

    С нами с:
    27 мар 2008
    Сообщения:
    63
    Симпатии:
    0
    ничего подобного, если сделаете var_dump($b) в конце, то увидите, что она указывает на основной массив и соотв. тоже изменилась, копирования не происходит
     
  16. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    Да, в $c что то типа ссылки на $a , но при изменении $c объект копируется, это без вопросов, но это не еще одна ссылка на $a, фактически это копия $a
    А как по твоему хранятся СТАТИЧНЫЕ массивы?))) $a не становится ссылкой на массив, она так и остается массивом (если отталкиваться от уровня php, а не ниже), просто часть $a, а именно $a[1] фактически становится отдельным объектом на который ссылается $b

    Тут не понял, с чего ты взял что она указывает на основной массив, ты посмотри var_dump($a), в нем $a[1] по ссылке хранится
     
  17. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
  18. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    Смотрим 2
    PHP:
    1. <?php
    2. $a = array('qw', array('as', 'as'));
    3.  
    4. echo '<br>';
    5.  
    6. $tmp = $a[1];
    7. $a[1] = &$tmp;
    8. $b = &$tmp;
    9.  
    10. echo '<br>';
    11.  
    12. $c = $a;
    13.  
    14. echo '<br>';
    15.  
    16. unset($c[1][1]);
    17.  
    18. echo '<br>';
    19.  
    20. echo '<br>';
    21. ?>
     
  19. alBoo

    alBoo Активный пользователь

    С нами с:
    27 мар 2008
    Сообщения:
    63
    Симпатии:
    0
    да, ступил :)
    беру свои слова обратно
     
  20. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    alBoo
    Да не, я наверное херово объяснил, но баг интересный, столько геммороя может в самый неподходящий момент доставить, устранять его я считаю надо, посмотрим что в пхп6 будет, кто нить знает когда выход?
     
  21. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    я думаю, он глубоко в архитектуре сидит.
     
  22. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    igordata
    Да, скорей всего, поэтому и не устраняют, просто наверное сейчас нет возможности сделать ссылку на часть массива, мб из-за того что адрес динамический или еще какой либо нюанс, и это как выход из положения, но слышал, что в пхп6 архитектура претерпит ряд глобальных изменений, вот хочу услышать, мб у кого информация есть
     
  23. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    Ссылки в пхп - это записи указывающие на одну и ту же структуру переменной. Именно по-этому это не совсем то, что ссылки в Си. Т.е. есть стуктура в памяти хранящая данные, есть таблица - имя/указатель на эту структуру. Ожидать, что можно будет не только указатель сделать, но еще и на какую-то субстуктуру указать - странно.
    Так что от понимания того, как работают ссылки становится все более-менее логично.
    Ссылки вообще вещь не прозрачная, а в связи с тем, что есть ссылки в пхп - рождает кучу непонимания. Отсюда вывод - не изучив подробно как работают ссылки внутри ПХП - использовать их нельзя.
     
  24. karlozzz

    karlozzz Активный пользователь

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    MiksIr
    В идеале работая на языке высокого уровня, нужно знать только то что написано в документации и относится именно к высокому уровню, а уж способы хранения структур данных в памяти и подобные нюансы могут без предупреждения разработчиков меняться от версии к версии в интерпретаторе
     
  25. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    Это ваши домыслы о том, что нужно, а что не нужно знать. Они особо никого не интересуют. Те, кто использует возможности языка серьезно - читают документацию. А там, если не ошибаюсь, сказано, что ссылки внутри массива - опасны.