Глубокая копия массива на Фортране

Мне нужна глубокая копия (настоящего) массива на Фортране (90), но я точно не знаю, как ее получить, так как не совсем понимаю, как работают ссылки. Интуитивно я ожидал, что это даст мне то, что я хочу:

do i=1,n
  b(i) = a(i)
end do

Однако недавно мне было указано, что b(1:n) = a(1:n) эквивалентен приведенному выше коду. Интуитивно я ожидал бы, что b(1:n) = a(1:n) просто заставляет ссылку b(1:n) указывать на расположение a(1:n) в памяти.

Является ли b(1:n) = a(1:n) глубокой копией? Почему? Что происходит с базовыми ссылками в отличие от b = a?


person astay13    schedule 03.08.2012    source источник


Ответы (2)


Все три способа копирования массивов, которые вы упомянули, цикл do, b(1:n) = a(1:n) и b = a эквивалентны; они копируют содержимое массива a в массив b. a и b — это просто массивы, а не причудливые указатели или что-то в этом роде, поэтому присваивание a = b в основном совпадает с математическим выражением. Нет никакого волшебства со ссылками (о которых пользователь должен знать), поэтому Fortran — довольно простой язык для изучения. У вас могут быть массивы указателей в Fortran, но это совсем другая проблема.

Объяснение Fortran 90/95 М. Меткалфа и Дж. Рида всегда является хорошим справочным материалом для получения консультаций по возможностям языка Fortran. Со страницы 48:

3.11 Назначение массива

С помощью внутреннего присваивания выражение массива может быть присвоено переменной массива той же формы, что интерпретируется так, как если бы каждый элемент выражения был присвоен соответствующему элементу переменной. Например, с объявлениями

real, dimension(10, 20) :: a

Назначение

a = a  + 1.0

заменяет a(i,j) на a(i,j) + 1.0 для i=1,2..,10 и j=1,2,..,20.

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

С точки зрения того, как все это на самом деле реализовано, к чему, я думаю, вы ведете свой вопрос, это совершенно не указано в стандарте Fortran. Такого рода вещи оставлены неопределенными, чтобы позволить авторам компиляторов делать любые оптимизации, которые им нужны. Например, в присваивании a = b порядок, в котором элементы b копируются в a, стандартом не определен, поэтому разные компиляторы могут делать это по-разному. Все, что вам нужно знать, это то, что для этого вопроса, если a и b не являются указателями, то a и b являются разными массивами и что изменение элемента одного не изменяет соответствующий элемент другого. Таким образом, a=b — это глубокая копия, и вы можете думать об этом как о копировании всех элементов в b в ячейку памяти a.

person Chris    schedule 03.08.2012
comment
@IanH Я не так много знаю об этом, поэтому в своем ответе я сосредоточился на массивах. Было бы интересно увидеть пример того, как вышеизложенное не относится к производным типам, если вы хотите опубликовать ответ. - person Chris; 04.08.2012
comment
Извиняюсь за эту болтовню, это был незаконченный пузырь мыслей, который, как я решил, не имеет отношения к вопросу (учитывая, что на плакате конкретно упоминаются РЕАЛЬНЫЕ переменные). Я даже не знал, что это было опубликовано. - person IanH; 05.08.2012
comment
b(1:n) = a(1:n) и b = a не эквивалентны. Например, первый не будет проверять необходимое перераспределение. - person Vladimir F; 18.10.2012

a = b копирует весь массив b в a. Если вам нужна только часть массива с размерами больше n, вы можете использовать индексную нотацию a(1:n) = b(1:n). Это Fortran 90 — это язык более высокого уровня, чем FORTRAN 77. Мы можем сказать, что «a = b» — это копия, а не ассоциирование указателя a с целью b, потому что в этом операторе использовался оператор «=». Ассоциация указателей использует =>.

Редактировать: копируя, он создает дубликат, вероятно, с тем же машинным кодом, что и ваш цикл do. Ассоциация указателя создает ссылку без выполнения цикла do для дублирования всех элементов массива.

См. http://en.wikipedia.org/wiki/Fortran_95_language_features.

person M. S. B.    schedule 03.08.2012
comment
Как это копирует? Перенаправив ссылку a на позицию b в памяти или переместив копию всех элементов в b на позицию a в памяти? - person astay13; 03.08.2012
comment
@ astay13, Fortran — это не Java и не C#. У него нет ссылок. У него есть указатели, но они используют специальный синтаксис для ассоциации, как указал MSB (=> вместо =). Например, gfortran реализует копирование массива с использованием либо memcpy (побитовое копирование памяти, очень быстрое), либо скрытых циклов DO, в зависимости от контекста. - person Hristo Iliev; 04.08.2012
comment
@HristoIliev, да, вопрос возникает, потому что Java - мой первый язык, поэтому я привык думать о том, что = используется для присваивания ссылок. - person astay13; 06.08.2012