Как dup работает с неровными массивами?
Я ожидал бы, что он будет дублировать только фрагменты вложенных массивов вместо всей глубокой копии массива, но внезапно у меня возникло сомнение.
1 ответ
Уродец прав, это мелкая копия. Вы можете увидеть исходный код функции dup в dmd2/src/druntime/src/rt/life.d. Функция называется _adDupT.
Это довольно короткая функция, основной задачей которой является вызов memcpy(). Над функцией вы можете увидеть представление массива: struct { size_t length; void* ptr; }
Зубчатый массив будет массивом массивов, поэтому память будет выглядеть как [length0, ptr0, length1, ptr1, length2, ptr2....]
Так как memcpy над этими указателями не следует за ними, это означает, что slice.dup является поверхностной копией.
Это в целом верно для всего, что копирует фрагменты, это всегда мелкие копии, если вы что-то не делаете сами. Так что struct A {char [] str; } A a, b; а = б; будет также поверхностное копирование, так что утверждаем (a.str - b.str).
Если вы хотите сделать глубокое копирование, самый простой способ - просто зациклить его:
T[][] newArray;
foreach(item; oldArray)
newArray ~= item.dup;
(вы также можете preallocat newArray.length = oldArray.length и назначать индексы, если хотите немного ускорить его)
Глубокая копия структуры могла бы быть сделана с отражением времени компиляции, хотя я предпочитаю написать метод клонирования или что-то там, так как это немного более ясно.
Я не знаю о функции Фобоса с этим готовым.