Сравнение стратегии возврата массивов - PullRequest
7 голосов
/ 05 января 2011

В Фортране я могу вернуть массивы из подпрограммы с тремя подходами. Первый - через параметр intent(out). Второй - через функцию с массивом result. Третий - иметь функцию, имеющую в качестве result указатель на массив, который размещен в функции.

Каковы преимущества и недостатки каждого подхода?

Ответы [ 2 ]

5 голосов
/ 05 января 2011

Моя практика заключается в использовании функции return, когда функция изменяет только одну переменную и не выводит никаких других выходных данных. Если несколько переменных изменены или процедура выполняет другие действия, я бы поместил выходные переменные в список аргументов. Это выбор стиля. Утечки памяти можно создавать с помощью указателей, особенно с указателями, возвращаемыми в качестве аргументов функции, поэтому я бы избегал этой опции, если в конкретном случае не было веской причины.

ОБНОВЛЕНИЕ: нет проблем с аргументом массива intent (out) ... не нужно делать предположений относительно размера массива, как показано в следующем примере:

module example_one

implicit none

contains

subroutine two_arrays ( in_arr, out_arr )

   integer, dimension (:), intent (in) :: in_arr
   integer, dimension (:), allocatable, intent (out) :: out_arr

   integer :: i, len

   len = size (in_arr)

   allocate ( out_arr (1:len) )

   do i=1, len
      out_arr (i) = 3 * in_arr (i)
   end do

return

end subroutine two_arrays

end module example_one


program test

use example_one

implicit none

integer, dimension (1:5)  :: in_arr = [ 1, 2, 4, 5, 10 ]
integer, dimension (:), allocatable :: out_arr

write (*, *) allocated ( out_arr)
call two_arrays ( in_arr, out_arr )

write (*, *) size (out_arr)
write (*, *) out_arr

write (*, *) allocated ( out_arr)
deallocate ( out_arr )
write (*, *) allocated ( out_arr)

stop

end program test
0 голосов
/ 05 января 2011
  1. `intent (out)` может быть проблемой, так как вы должны делать предположения о размере передаваемого массива.
  2. возврат массива также является проблемой, так как получающий код будетприходится делать предположения о размере возвращаемого массива
  3. указатели на массивы имеют проблемы, связанные с размером, а также проблему принятия предположений о том, связан указатель или нет.
  4. альтернативаэто создать модуль, и в этом модуле есть тип, который содержит как размещаемый массив, так и целое число, детализирующее размер массива:
module mymodule
    type myvector
        double precision,allocatable::values(:)
        integer::length
    end type
end module

Тогда ваша функция может быть:

function myvecreturner(someparam)
    use mymodule
    type(myvector)::myvecreturner
    integer::someparam

    allocate(myvecreturner%values(someparam))
    myvecreturner%length = someparam
end function

И вы можете счастливо передавать эти типы myvector.Просто не забудьте освободить массивы, когда закончите с ними ...

...