unique pointer としての allocatable
Fortran 90 で導入された allocatable 属性は、F90 の時点では自動解放されず、他の変数に associate 出来ないだけで pointer と大して変わりないものでした。Fortran 95 で subroutine/function の副プログラムから出る時に、その中で定義した allocatable 変数は自動解放するようになって安全・安心wになりました。また move_alloc subroutine も導入され、pointer 的な shallow copy も可能としました。( Fortran 2008 からは、新たに導入された block 構造を抜ける時にも block 内で定義した allocatable 変数は自動解放されます。)
当初、Fortran の allocatble は、普通の科学者・技術者ごときには高邁なる pointer が理解できないだろうからと導入されたものでしたが、30年近くたって今をときめく流行りの新言語では生の pointer が否定されるようになり、安全性を高めた allocatable 的なものが自画自賛されながら導入されているのが面白いところです。
Fortran の allocatable は、target 属性を付けると pointer で associate 出来るようになり、確保先の heap の番地先が unique でなくなります。この場合 pointer が allocatable 変数に associate されていると、allocatable 変数の自動解放が行われた後 associate 先が存在しないことになります。(pointer 型の変数に associate した場合は、pointer 変数は自動解放されないので associate 先が残りますが手動で解放する必要があります。
Modern Fortran: Building efficient parallel applications
- 作者:Curcic, Milan
- 発売日: 2020/11/24
- メディア: ペーパーバック
How to learn Applied Mathematics through modern FORTRAN
- 作者:Hernandez Ramos, Juan Antonio,Escoto Lopez, Javier
- 発売日: 2020/02/23
- メディア: ペーパーバック
allocatable
program unique2 implicit none integer :: i real, pointer :: p(:) block real, allocatable, target :: a(:) ! real, pointer :: a(:) allocate(a(10**8)) a = 9.9999 p => a print *, size(a) pause end block print *, size(p), associated(p) print *, (p(1:10)) pause end program unique2
100000000 Fortran Pause - Enter command<CR> or <CR> to continue. 100000000 T forrtl: 致命的なエラー (157): プログラム例外 - アクセス違反 Image PC Routine Line Source unique2.exe 00007FF6F25B1745 MAIN__ 15 unique2.f90 unique2.exe 00007FF6F25B17EE Unknown Unknown Unknown unique2.exe 00007FF6F25B4329 Unknown Unknown Unknown unique2.exe 00007FF6F25B424E Unknown Unknown Unknown unique2.exe 00007FF6F25B410E Unknown Unknown Unknown unique2.exe 00007FF6F25B439E Unknown Unknown Unknown KERNEL32.DLL 00007FFCD9A27034 Unknown Unknown Unknown ntdll.dll 00007FFCDBA02651 Unknown Unknown Unknown
pointer
program unique2 implicit none integer :: i real, pointer :: p(:) block ! real, allocatable, target :: a(:) real, pointer :: a(:) allocate(a(10**8)) a = 9.9999 p => a print *, size(a) pause end block print *, size(p), associated(p) print *, (p(1:10)) deallocate(p) pause end program unique2
100000000 Fortran Pause - Enter command<CR> or <CR> to continue. 100000000 T 9.999900 9.999900 9.999900 9.999900 9.999900 9.999900 9.999900 9.999900 9.999900 9.999900 Fortran Pause - Enter command<CR> or <CR> to continue. 続行するには何かキーを押してください . . .