powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / php - как всё же должно быть и почему (массивы в функциях)
22 сообщений из 22, страница 1 из 1
php - как всё же должно быть и почему (массивы в функциях)
    #38339210
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.
Как говорится "век живи - век учись", а в плане php это выражение приобретает ещё более глубокий смысл
Итак, возник такой вопрос, в большом проекте с моим участием был найден очень неприятный косяк. Начал исследовать проблему... и вот что нашёл.
Думаю все знают, что пхп с передачей массивов в функцию очень хитёр. Он передаёт массив по ссылке, но при попытке что-то изменить быстренько создаёт дубликат массива и продолжает работу уже с ним не меняя значений основного массива. Но так происходит не всегда. Может кто знает почему?
Показательный код:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<?
class b{
   public $a=5;
   public function setA(){
       $this->a=3;
   }
}
function a1($arr){
 $arr[0]->setA();
}
function a2($arr){
 $arr[1]->a=4;
}
function a3($arr){
 $arr[2][0]=5;
}
$a = array(new b(), new b(), array(1,2,3,4)); //итак, передали... массив из двух объектов и вложенного массива
a1($a); //меняем атрибут вложенного объекта с помощью функции класса
a2($a); //меняем атрибут объекта напрямую
a3($a); //меняем один из элементов вложенного массива
var_dump($a); //массив с двумя изменёнными объектами и не изменённым массивом
?>



Почему изменение вложенного массива отслеживается (и создаётся копия), а объекта - нет. Вопрос, как это отслеживание было организовано, ведь для основного массива все его элементы - это ссылки, а значит отслеживаться должны одинаково (или изменение ссылки или изменение значения по ссылке).

Выскажите пожалуйста своё мнение о логичности/нелогичности данного поведения. Просто уж очень хочется понять принцип работы, сами понимаете, любой косяк может вылиться в огромную сумму у кучу неприятностей, а такое поведение может ещё не к одному косяку привести.

Заранее благодарен.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339218
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор. Он передаёт массив по ссылке
нет

авторМожет кто знает почему?
copy - on - write
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339248
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторObjects and references ¶

One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default".
http://php.net/manual/en/language.oop5.references.php
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339294
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowавтор. Он передаёт массив по ссылке
нет
В очередной раз придётся с Вами спорить и доказывать, что Вы не правы?
ScareCrowавторМожет кто знает почему?
copy - on - write
Хотя не придётся. Вы сами с собой походу спорите. Кстати, это не ответ на мой вопрос, а просто переформулировка сказанного выше с помощью общепринятого термина.
ScareCrowавторObjects and references ¶

One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default".
http://php.net/manual/en/language.oop5.references.php
Это также не ответ на мой вопрос. Однако, написанного по ссылке не понял, так как не вижу принципиальной разницы между handle'ом объекта и указателем на сам объект. То есть, handle - это просто метод нелинейной адресации пространства (то есть в конечном счёте это просто значение, которое будет преобразовано в указатель).

Если считаете, что я не прав, поясните пожалуйста своими словами, почему считаете, что должно быть так (и как именно должно быть), и тогда подкрепите ссылкой. Возможно я просто не понял о чём Вы хотели сказать.

Тема остаётся открытой, основной вопрос актуален.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339301
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автортак как не вижу принципиальной разницы между handle'ом объекта и указателем на сам объект
теперь вам осталось убедить в этом PHP и все будет хорошо.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339418
?
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
?
Гость
Програмёр, массив тут вообще не при чем. Можете просто передать объект и будет тот же эффект.
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
<?
class b{
   public $a=5;
   public function setA(){
       $this->a=3;
   }
}
function a($b){
 $b->setA();
}
$a = new b();
a($a);
var_dump($a);
?>

Объекты вообще не копируются, копируются ссылки на них.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339464
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowавтортак как не вижу принципиальной разницы между handle'ом объекта и указателем на сам объект
теперь вам осталось убедить в этом PHP и все будет хорошо.

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<?
class b{
   public $a=5;
   public function setA(){
       $this->a=3;
   }
}
function a1($arr){
 $arr[0]->setA();
}
function a2($arr){
 $arr[1]->a=4;
}
function a3($arr){
 $arr[2]["#0"][0]=5; // обращаемся к массиву по его handle (#0)
}
$a = array(new b(), new b(), array("#0"=>array(1, 2, 3), "#1"=>array(1, 2, 3)));
a1($a);
a2($a);
a3($a);
var_dump($a);
?>



Зная принцип преобразования handle'ов в адреса не надо никому ничего доказывать. Вот Вам пожалуйста, работа с массивом по его хэнделу в системе (в данном случае по локальному).

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

За беседу спасибо. Тему можно закрыть.

P.S. Так что, перед изменением элемента-объекта в функции просто вызываем $arr[$key]= clone $arr[$key] и изменение объектов останется только внутри функции (так как проводиться будут с дубликатами). Так по крайней мере была решена моя проблема.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339473
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор$arr[2]["#0"][0]=5; // обращаемся к массиву по его handle (#0)
ты сделал мой день.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339479
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторак что, перед изменением элемента-объекта в функции просто вызываем $arr[$key]= clone $arr[$key]
ты эта. только не говори что это тебе на нашем форуме посоветовали, когда тебя бить будут.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339483
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
?,

спасибо. Ваше сообщение не видел когда своё писал. Вы правильно сказали, но основной вопрос был не в том, почему не копируются объекты, а почему обработка объекта в такой ситуации так отличается от обработки массива (ведь во вложенном массиве и то и другое - это ссылки). И логика прослеживается только одна, что разработчики решили все массивы обрабатывать так же, как и обычные базовые типы языка, а соответственно все массивы вложенные в основной массив (и все массивы второго, третьего, четвёртого и т.д.) уровней будут продублированы точно так же, как и любое значение базового типа. Вот и всё.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339484
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторведь во вложенном массиве и то и другое - это ссылки
ты хоть доку почитай ради приличия.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339512
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowавтор$arr[2]["#0"][0]=5; // обращаемся к массиву по его handle (#0)
ты сделал мой день.

Когда нечего сказать, но жуть как хочется ответить

ScareCrowавторведь во вложенном массиве и то и другое - это ссылки
ты хоть доку почитай ради приличия.

Ссылку пожалуйста. И Ваш вариант (своими словами)

ScareCrowавторак что, перед изменением элемента-объекта в функции просто вызываем $arr[$key]= clone $arr[$key]
ты эта. только не говори что это тебе на нашем форуме посоветовали, когда тебя бить будут.

Откликнитесь пожалуйста те, кто хочет меня побить за это. И если можно те, кто считает это правильным решением задачи в мегабайтах кода (когда не всегда даже получается отследить где всё началось и где закончилось).
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339526
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
typedef union _zvalue_value {
    long lval;                // For integers and booleans
    double dval;              // For floats (doubles)
    struct {                  // For strings
        char *val;            //     consisting of the string itself
        int len;              //     and its length
    } str;
    HashTable *ht;            // For arrays (hash tables)
    zend_object_value obj;    // For objects
} zvalue_value;
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339564
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrow http://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
typedef union _zvalue_value {
    long lval;                // For integers and booleans
    double dval;              // For floats (doubles)
    struct {                  // For strings
        char *val;            //     consisting of the string itself
        int len;              //     and its length
    } str;
    HashTable *ht;            // For arrays (hash tables)
    zend_object_value obj;    // For objects
} zvalue_value;



И ЭТО называется доками?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
typedef struct bucket {
    ulong h;                  // The hash (or for int keys the key)
    uint nKeyLength;          // The length of the key (for string keys)
    void *pData;              // The actual data
    void *pDataPtr;           // ??? What's this ???
    struct bucket *pListNext; // PHP arrays are ordered. This gives the next element in that order
    struct bucket *pListLast; // and this gives the previous element
    struct bucket *pNext;     // The next element in this (doubly) linked list
    struct bucket *pLast;     // The previous element in this (doubly) linked list
    const char *arKey;        // The key (for string keys)
} Bucket;



Порадовала надпись "??? What's this ???" в описании структуры. Хорошо исследования проводили, что даже не поняли, что это всего лишь указатель на значение, которое может находиться в любом участке памяти, так как массивы в пхп являются динамическими и память под них выделяется также динамически и никогда не известно заранее, куда следующий элемент будет записан.

По статье вообще объяснений давать не намерен. Долго и в данном случае требует полного пересказа тут. Вы вообщем не то выбрали. Речь идёт о другом. Если в кратце, неужели Вы думаете, что вся структура (144 байта * количество элементов) записывается как элемент массива при вкладывании одного массива в другой. Туда кладётся ссылка на эту структуру. А это именно то, о чём я говорил. Внутреннее устройство структуры hash массивов в php меня не очень интересует и по сути темы не касается (хотя почитать было интересно).
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339571
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
надеюсь из этой статьи вы поняли отличие между хеш таблицей массива и zend_object_value для объекта?
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339592
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowнадеюсь из этой статьи вы поняли отличие между хеш таблицей массива и zend_object_value для объекта?

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

Но кстати, данную статью Вы мне скинули не с той целью, что бы показать разницу между хэндлом и ссылкой, а с той, что бы доказать, что массив записывается не как ссылка на структуру памяти, а как что-то иное. Доказательств так и не увидел.

В принципе общение с Вами является скучным, как и обычно Ваши ссылки не соответствуют Вашим словам, а везде, где нечего ответить следует "ты сделал мой день". Так что если нету реально чего-то стоящего (подкреплённого чем-то официальным или хотя бы источником с высоким уровнем доверия), тогда давайте прекращать бессмысленные беседы и трату времени. Мне ещё работать однако :)
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339595
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну если исходники php для вас недостаточно официальны - то идите работать.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339638
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowну если исходники php для вас недостаточно официальны - то идите работать.

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

Тема закрыта.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38339649
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ага, так бы сразу и сказали то и тут ничего не поняли. ну извините, комиксов у меня нет.

Модератор:
ScareCrow , позвольте напомнить, что Вы находитесь не в ПТ. Комиксы и "ты сделал мой день" здесь абсолютно неуместны. Если можете объяснить техническим языком что именно не так - излагайте. Нет - воздержитесь. Иначе придется немного отдохнуть от форума.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38341669
deblogger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По-моему тут неоправданно завышенные требования к такому чюду как php.

Пишите cgi на С.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38341989
Програмёр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
debloggerПо-моему тут неоправданно завышенные требования к такому чюду как php.

Пишите cgi на С.

Я бы с радостью... Да вот C знаю посредственно (хотя это исправить несложно в короткие сроки). Но вот самое сложное это то, что проект уже ведётся более года с постоянными исправлениями, дописываниями и т.д. И если сейчас начинать его переводить на С, это затянется очень на долго... неоправданно.
...
Рейтинг: 0 / 0
php - как всё же должно быть и почему (массивы в функциях)
    #38342593
deblogger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Програмёр,

Тема выродилась, а я вспомнил картинку. Чуваки на форуме, кажется devshed, прикалывались над методами обратных вызовов виндового API в бейсик, или типа того. В общем на рисунке сверху красная линия в загогулинах до невозможности, подпись - use callback. Внизу красная линия начерчена абсолютно прямой и подпись: use control.

Суть такова: вместо колбэков втыкаем скрытый элемент управления, загружаем его данными, получаем обработанные данные и выводим в открытый элемент управления.

Например на железобетонном васике в отличии от пластилиновых скриптов сортировка многомерных массивов дело не такое простое. Ссылками (byRef) пользовался сугубо в исключительных случаях, потому что как начнешь - так сразу запутаешься нафиг. Всегда работал с копиями, но с этой сортировкой без рефа никак. Ну вот, а можно тупо взять какой-нибудь listview, спрятать, настроить один раз, загрузить, сортировать и получить что угодно в кратчайшие сроки.

Когда начал писать на яваскрипте потратил наверное целый час чтобы убедиться в отсутствии необходимости объявлять типы данных. Затем массивы массивов меня привели в полный восторг. Неудивительно что массы пишут на js, а не на vbs. Микрософт тут, конечно, не при чем.

Кстати, недавно js меня и подогрел своими массивами массивов. Надо было прочитать список файлов и закинуть его в екзель. Так вот оказалось что екзель запросто понимает многомерный массив - то есть из vba можно буквально вставить, а массив-массив из js в упор не видит. Пришлось построчно вписывать. Ну не писать же на vbs ради одного косячка в js. :)

Я просто хочу сказать что нельзя к скриптовму языку предъявлять повышенные требования. Все равно вы ничего не контролируете, у вас нет компилятора, нет объектной библиотеки, нет ничего кроме мануала по скрипту.

Нашли косяк - расскажите как обойти. :)
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / php - как всё же должно быть и почему (массивы в функциях)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]