数组的动态分配
a) 可分配数组
数组可以是静态的也可以是动态的。如果数组是静态的,则在编译时就被分配了固定的储存空间,并且直到程序退出时才被释放。程序运行时静态数组的大小不能改变。静态数组的缺陷是,即使数组已经使用完毕,它仍占据着内存空间,浪费了系统资源。在给定的计算机内存资源情况下,耗费了其他数组可以利用的内存,并且超过资源的数组将导致程序执行错误。因此,F90增加了动态的数组功能,动态数组的储存在程序运行当中是可以分配、改变和释放的。
动态数组只有两种:可分配数组和自动数组。自动数组和可分配数组很类似,区别在于当程序开始或结束时,自动数组会自动分配和释放内存。当用户分配动态存储空间时,数组的大小是在运行时而不是在编译时确定的。动态分配可以用于标量和任何类型的数组。当用户给数组指定了可分配属性时并没有立即分配内存,而是直到使用ALLOCATE语句后才分配。随后还可以用DEALLOCATE语句释放内存空间,这时数组可以以其它形状或目的来使用。
应该注意的是,WinNT/9x上运行的Visual Fortran动态内存分配受一些因素的限制,包括交换文件的大小和其它同时运行的应用程序所需的内存大小。如果动态分配的内存太大或试图使用其它应用程序的保护内存会产生一般内存保护错误。碰到这类问题可以通过控制面板来改变虚拟内存的大小或交换文件的大小,还有一些编程技术可以降低内存需要。
b) ALLOCATE语句
ALLOCATE语句动态创建可分配数组,使内存和对象相联系。分配的对象可以被命名为任何有ALLOCATABLE属性的变量。它的一般形式为:
ALLOCATE(数组名[维界符][,数组名[(维界符[,维界符...])] ] ...[,STAT=状态值])。
例:REAL A(:),B(:,:,:)
ALLOCATABLE A,B
ALLOCATE(A(-2:40),B(3,3,3))
当数组被分配时,内存分配给指定大小的数组。ALLOCATE语句中的秩必须和可分配数组的秩相同。在分配的同时,ALLOCATE语句中的上下界决定了数组的大小和形状。边界的值可以是正数、负数或零,缺省的下界为1。如果维上界比下界小,则该维的长度为零,并且数组的大小为零。大小为零的数组不能被赋值。
当前被分配的数组不能被再分配,否则会引起运行错误。错误状态可以由ALLOCATE语句中的STAT值获得。如果指定STAT选项,语句的成功执行时将返回0,否则返回正值。若未指定STAT选项且出现错误时,程序将中止执行。
例:INTEGER, ALLOCATABLE :: A(:),B(:)
INTEGER ERR_MESSAGE
ALLOCATE(A(10:25),B(SIZE(A)),STAT=ERR_MESSAGE)
IF(ERR_MESSAGE.NE.0) PRINT *,'ALLOCATION ERROR'
可以用内在函数ALLOCATED来判断一个数组是否已被分配。它的形式为:ALLOCATED(数组名)。返回值是逻辑标量,已被分配时为真,现在还未被分配时为假,当数组的分配状态未定义时它也是未定义的。
例:REAL, ALLOCATABLE :: A(:)
...
IF(.NOT.ALLOCATED(A)) ALLOCATE(A(5))
c) DEALLOCATE语句
DEALLOCATE语句用来释放已分配数组的内存。它的一般形式为:DEALLOCATE(数组名[,数组名]...[,STAT=状态值])。
例:INTEGER, ALLOCATABLE :: A(:),B(:)
INTEGER ERR_MESSAGE
ALLOCATE(A(10:25),B(SIZE(A)))
DEALLOCATE(A,B,STAT=ERR_MESSAGE)
IF(ERR_MESSAGE.NE.0) PRINT *,'DEALLOCATION ERROR'
例:INTEGER,DIMENSION(:),ALLOCATABLE :: freq
READ *,limit
ALLOCATE(freq(1:limit))
DEALLOCATE(freq)
只有被ALLOCATE语句分配的内存空间才可以被DEALLOCATE语句释放,否则产生运行错误。可以使用ALLOCATED语句判断数组是否被分配,错误状态可以由ALLOCATE语句中的STAT值获得。
当过程的执行被RETURN或END语句中止时,除非可分配数组是有SAVE属性的,否则它的分配状态变成未定义的。但是,RETURN和END语句并不释放数组分配的内存,所以应该在退出子程序前主动释放数组分配的内存。
可分配数组的联合状态可以是已分配的(该数组被ALLOCATE语句分配,可以被引用、定义或释放)或是目前未联合(该数组从未分配或上一个操作是释放,数组不能被引用或定义)。
当可分配数组赋值时就被定义。
例:INTEGER, ALLOCATABLE :: A(:)
ALLOCATE(A(100)) ! A被分配但未定义,A的分配状态是己分配
A(1:100)=1 ! A被定义
DEALLOCATE(A) ! A被释放,A的分配状态是未分配
本文来自大学力学论坛(http://www.xuelixue.cn)