Tablice możliwe do przydzielenia#
Atrybut allocatable
pozwala na bezpieczną obsługę pamięci. W porównaniu z atrybutem zmiennych pointer
pamięć jest obsługiwana automatycznie i zostanie zwolniona w momencie, gdy zmienna wyjdzie poza zakres. Używanie atrybutu allocatable
dla zmiennych zmniejsza prawdopodobieństwo powstania przecieków pamięci w aplikacji.
Mogą być używane w podprogramach, aby stworzyć tablice podstawowe lub robocze, gdzie automatyczne tablice mogłyby stać się zbyt duże, aby zmieścić się na stosie.
real(dp), allocatable :: temp(:)
allocate(temp(10))
Status przydziału można sprawdzić za pomocą funkcji allocated
, aby uniknąć niezainicjowanego dostępu
subroutine show_arr(arr)
integer, allocatable, intent(in) :: arr(:)
if (allocated(arr)) then
print *, arr
end if
end subroutine show_arr
Aby przydzielić zmienne wewnątrz procedury fikcyjny argument musi posiadać atrybut allocatable
. Użycie go w połączeniu z intent(out)
zwolni poprzednie przydziały zanim rozpocznie się wykonywanie procedury:
subroutine foo(lam)
real(dp), allocatable, intent(out) :: lam(:)
allocate(lam(5))
end subroutine foo
Przydzielona tablica może być później używana jak normalna tablica
real(dp), allocatable :: lam(:)
call foo(lam)
Przydzielona już tablica nie może zostać przydzielona ponownie bez wcześniejszego zwolnienia przydziału. Zwolnienie przydziału również może być rozpoczęte tylko dla przydzielonych już tablic. Aby zmienić przydział tablicy użyj
if (allocated(lam)) deallocate(lam)
allocate(lam(10))
Przekazywanie przydzielonych tablic do procedur nie wymaga już użycia atrybutu allocatable
dla fikcyjnego argumentu.
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
Przekazywanie nieprzydzielonej tablicy w tym kontekście doprowadzi do niepoprawnego dostępu do pamięci. Przydzielone tablice mogą być przekazywane do opcjonalnych (optional
) argumentów fikcyjnych - w przypadku nieprzydzielenia tablicy argument nie będzie obecny. Atrybut allocatable
nie jest ograniczony tylko do tablic i może być używany również do wielkości skalarnych, co może być przydatne w połączeniu z opcjonalnymi ( optional
) argumentami fikcyjnymi.
Przydziały mogą być zmieniane pomiędzy różnymi tablicami przy użyciu atrybutu allocatable
oraz wewnętrznego podprogramu 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
Na koniec, przydziały nie inicjują tablic. Zawartością niezainicjowanej tablicy są prawdopodobnie bajty tego, co poprzednio znajdowało się pod tym adresem. Przydziały obsługują inicjalizację przy użyciu atrybutu source:
real(dp), allocatable :: arr(:)
allocate(arr(10), source=0.0_dp)
Słowo kluczowe source
obsługuje wartości skalarne, zmienne oraz stałe.