2011-01-05 2 views
6

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

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

ответ

5

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

UPDATE: Там нет никаких проблем с намерением (уходит) аргумент массива ... никаких предположений не нужно быть размером массива, как показано в следующем примере:

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

Есть ли проблемы, такие как сбои стека, когда вы возвращаетесь с помощью разных стратегий? предположим, что вы возвращаете массив из 1 миллиона реалов. вы переполните стек и скопируете ли он из контекста функции в контекст вызывающего? –

0
  1. `умысел (out) `может быть проблемой, так как вам приходится делать предположения о размере передаваемого массива.
  2. Возвращение массива также является проблемой, так как получающий код должен будет делать предположения о размере возвращаемого массива
  3. указатели на массивы имеют проблемы, связанные с размером плюс проблема o f делает предположения о том, связан ли указатель или нет.
  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. Просто не забудьте освободить массивы, когда вы закончите с ними ...

+1

Ну, технически, вы уже несете размер массива, без необходимости в типе. запрос с 'size' достигает такого же эффекта. –

+0

Существуют также решения для # 2. Функции могут возвращать распределяемые массивы. См. Http://stackoverflow.com/questions/4647772/function-returning-array-with-no-defined-explicit-shape –