Как 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 и назначать индексы, если хотите немного ускорить его)

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

Я не знаю о функции Фобоса с этим готовым.

Другие вопросы по тегам