В ответе Стива Лайонела и комментариях в моем первоначальном ответе, которые, возможно, вызвали этот интерес, влияние intent(out)
на начальное состояние фиктивного аргумента (и фактического аргумента) является одним из способовЧтобы ответить на этот вопрос.
intent(inout)
имеет фиктивный аргумент, отражающий значение фактического аргумента при входе в процедуру. intent(out)
"сбрасывает" фиктивный аргумент. В случае связанного вопроса это «неопределенность» является причиной неправильной природы программы.
Точнее, о intent(out)
фиктивных аргументах можно сказать следующее:
- выделяемые фактические аргументы становятся освобожденными;
- связь указателя с действительными аргументами указателя становится неопределенной;
- для фиктивного аргумента без указателя любой компонент, не инициализированный по умолчанию, становится неопределенным.
Связанный вопрос нарушил третью точку, пытаясь сослаться на такое новое неопределенное значение. Однако инициализированные компоненты по умолчанию не являются неопределенными, что приводит нас к нашему первому классу допустимых программ:
implicit none
type t
integer :: x=1
end type t
type(t) :: x=t(0)
call s1(x)
call s2(x)
contains
subroutine s1(x)
type(t), intent(inout) :: x
print*, x%x
end subroutine s1
subroutine s2(x)
type(t), intent(out) :: x
print*, x%x
end subroutine s2
end
Важно, что инициализация компонента по умолчанию означает, что x%x
не является неопределенным даже при входе в s2
, но оно потенциально может отличаться от фактического компонента аргумента до ввода процедуры.
Создать подходящую программу с аргументами-указателями довольно сложно: на указатель с неопределенным статусом ассоциации указателя нельзя ссылаться/ запрашивается до переопределения его статуса ассоциации указателей.
Что оставляет нас в поиске выделяемых компонентов. В отличие от указателей, где мы не можем запрашивать статус ассоциации указателя, когда он не определен, мы можем спросить о статусе выделения. Фактический аргумент, соответствующий манекену intent(out)
, освобождается;с intent(inout)
статус распределения не изменяется:
implicit none
integer, allocatable :: i
allocate (i)
call s1(i); print*, allocated(i)
call s2(i); print*, allocated(i)
contains
subroutine s1(i)
integer, allocatable, intent(inout) :: i
end subroutine s1
subroutine s2(i)
integer, allocatable, intent(out) :: i
end subroutine s2
end
(Это более простая версия примера Стива Лайонела.)
Все это показывает, что возможны различия. Неправильное использование intent
может привести к неправильным программам или значительным изменениям в значении. Понимание того, что означают intent(in)
, intent(inout)
, intent(out)
и отсутствие определенного намерения, является важной частью работы программиста на Фортране.