可分配数组#
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
关键字支持标量和数组值变量和常量。