可分配数组#

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

在此上下文中传递未分配的数组将导致无效的内存访问。可分配数组可以传递给 optional 虚拟参数 - 如果它们未分配,则该参数将不存在。 allocatable 属性不限于数组,也可以与标量相关联,这在与 optional 虚拟参数结合使用时非常有用。

可以使用 move_alloc 内在子程序在具有 allocatable 属性的不同数组之间移动分配。

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 关键字支持标量和数组值变量以及常量。