Выделяемые (динамические) массивы#

Аттрибут allocatable обеспечивает безопасный способ работы с памятью. По сравнению с переменными с атрибутом pointer память управляется автоматически и будет автоматически освобождена, как только переменная выйдет за пределы области видимости. Использование allocatable (выделяемых) переменных устраняет возможность создания утечек памяти в приложении.

Они могут быть использованы в процедурах для создания временных или рабочих массивов, в случаях, когда автоматические массивы были бы слишком большими, чтобы поместиться в стеке.

real(dp), allocatable :: temp(:)
allocate(temp(10))

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

subroutine show_arr(arr)
  integer, allocatable, intent(in) :: arr(:)

  if (allocated(arr)) then
    print *, arr
  end if
end subroutine show_arr

Для выделения памяти переменным внутри подпрограммы фиктивный аргумент должен иметь атрибут allocatable. Его использование в сочетании с атрибутом intent(out) приведёт к освобождению памяти из предыдущих её выделений перед входом в подпрограмму:

subroutine foo(lam)
  real(dp), allocatable, intent(out) :: lam(:)
  allocate(lam(5))
end subroutine foo

Выделяемый (динамический) массив в дальнейшем может быть использован как обычный массив

real(dp), allocatable :: lam(:)
call foo(lam)

Для массива, для которого была выделена память, не может быть выделена память без предварительного освобождения выделенной ранее памяти. Аналогично, освобождение памяти может быть выполнено только для массивов, для которых она была выделена. Для повторного выделения памяти массиву используйте

if (allocated(lam)) deallocate(lam)
allocate(lam(10))

Передача выделяемых (динамических) массивов в подпрограммы больше не требует использования атрибута allocatable для фиктивных аргументов.

subroutine show_arr(arr)
  integer, intent(in) :: arr(:)

  print *, arr
end subroutine show_arr

subroutine proc
  integer :: i
  integer, allocatable :: arr

  allocate(arr(5))

  do i = 1, size(arr)
    arr(i) = 2*i + 1
  end do
  call show_arr(arr)
end subroutine proc

Передача массива с невыделенной памятью этом контексте приведёт к некорректному доступу к памяти. Выделяемые (динамические) массивы могут быть переданы как необязательные фиктивные аргументы –- если им не выделена память, то аргументы не будут учитываться. Атрибут allocatable не ограничивается массивами и также может быть связан со скалярами, что может быть полезно в сочетании с необязательными фиктивными аргументами.

Выделенные области памяти могут быть перемещены между разными массивами, имеющими атрибут allocatable, с помощью встроенной процедуры move_alloc.

subroutine resize(var, n)
  real(wp), allocatable, intent(inout) :: var(:)
  integer, intent(in), optional :: n
  integer :: this_size, new_size
  integer, parameter :: inital_size = 16

  if (allocated(var)) then
    this_size = size(var, 1)
    call move_alloc(var, tmp)
  else
    this_size = initial_size
  end if

  if (present(n)) then
    new_size = n
  else
    new_size = this_size + this_size/2 + 1
  end if

  allocate(var(new_size))

  if (allocated(tmp)) then
    this_size = min(size(tmp, 1), size(var, 1))
    var(:this_size) = tmp(:this_size)
  end if
end subroutine resize

Наконец, выделение памяти не приводит к инициализации массива. Содержимое неинициализированного массива, скорее всего, представляет собой просто байты того, что ранее находилось по соответствующему адресу. Операция выделения памяти поддерживает инициализацию с помощью указания источника (source):

real(dp), allocatable :: arr(:)
allocate(arr(10), source=0.0_dp)

Ключевое слово source поддерживает использование скаляров, переменных в виде массива значений и констант.