2015-03-13 2 views
3

Согласно Fortran WikiIntel fortran компилятор версии 14 должен поддерживать окончательную доработку, определенную в стандарте FORTRAN 2003. Я попытался использовать эту функцию с ifort 14, но наблюдал странное поведение. Следующий пример должен показать это:Завершение разработки в FORTRAN 2003

module mtypes 
    implicit none 

    type mytype 
     integer, private :: nr 
     contains 

      final :: delete_mytype 
      procedure :: print_mytype 
    end type 

    contains 


!>  \brief Constructs a new mytype 
!!  \return The created mytype 
!> 
     function init_mytype(number) 
      type(mytype) :: init_mytype 
      integer, intent(in) :: number 
!   allocate(init_mytype) 
      init_mytype = mytype(number) 
      print *, 'init mytype', number 
     end function 

!>  \brief De-constructs a mytype object 
!> 
     subroutine delete_mytype(this) 
      type(mytype) :: this !< The mytype object that will be finalized 
      print *, 'Deleted mytype!', this%nr 
     end subroutine delete_mytype 

!>  \brief Print something from mytype object 
!> 
     subroutine print_mytype(this) 
      class(mytype) :: this !< The mytype object that will print something 
      print *, 'Print something from mytype!', this%nr 
     end subroutine print_mytype 


end module mtypes 

program main 

    use mtypes 
    type(mytype) :: t1, t2 

    call t1%print_mytype() 
    call t2%print_mytype() 

    t1 = mytype(1) 
    call t1%print_mytype() 
    t2 = init_mytype(2) 
    call t2%print_mytype() 

end program main 

В этом полном примере type mytype определено, что имеет только одно значение nr. Этот тип может быть создан с использованием простого конструктора типов, например. mytype(1) или инициализирующая функция init_mytype. Также определена подпрограмма print_mytype, которая просто печатает mytype%nr на стандартный вывод. Наконец, для окончательной доработки следует использовать подпрограмму finaldelete_mytype, хотя в данном примере она только печатает некоторую информацию в стандартный вывод.

Этот пример дает следующий результат:

Print something from mytype!   0 
Print something from mytype!   0 
Deleted mytype!   0 
Print something from mytype!   1 
Deleted mytype!   -2 
init mytype   2 
Deleted mytype!   0 
Deleted mytype!   2 
Print something from mytype!   2 
  • Линия 1: Хорошо, t1 инициализируется со значением по умолчанию 0
  • Line 2: Хорошо, t2 инициализируется значением по умолчанию 0
  • Line 3: Хорошо, после присвоения нового объекта t1%mytype(1) старая версия удалена
  • Строка 4: Хорошо, версия с nr = 1 напечатана
  • Строка 5: Странно, откуда взялась версия с nr=-2?
  • Line 6: Хорошо, версия с nr = 2 инициализируется
  • Линия 7: Хорошо, после присвоения нового объекта t2 = init_mytype(2) старая версия будет удалена
  • Строка 8: Странно, t2 будет завершена до вызова t2%print_mytype()
  • Строка 9: Странно, t2 печатается после финализации

Это странное поведение, вызванное некоторой ошибкой ifort или вызвано неправильным применением функции завершения FORTRAN 2003, и я делаю что-то неправильно?

+0

Было бы лучше установить значение по умолчанию в определении типа: integer, private :: nr = 0', чем полагаться на автоматическую инициализацию, выполняемую компилятором. При этом, насколько я знаю, ifort инициализирует все целые числа до нуля по умолчанию, поэтому я не уверен, что вызывает эти проблемы. На моей машине он печатает нуль на 5-й строке. –

ответ

4

Что кажется странным, на самом деле является результатом правил о завершении. В Fortran 2008 4.5.6.3 («При завершении») даются подсказки для завершения.

Перед тем, как приступить к этому, слово об инициализации. Вы говорите, что

Линия 1: Хорошо, t1 инициализируется со значением по умолчанию 0

Производный компонент nr тип не имеет инициализации по умолчанию, и нет явной инициализации для t1, поэтому ваше заявление ISN» t истинно. Фактически, t1%nr не определено в этот момент. 0 просто является результатом. Это важно, как мы видим позже.

Ваш код, с комментариями о финализации:

t1 = mytype(1)   ! t1 finalized before assignment 
call t1%print_mytype() 
t2 = init_mytype(2)  ! t2 finalized before assignment, after function 
         ! init_mytype result finalized after assignment 
call t2%print_mytype() 
         ! No finalization before END PROGRAM (4.5.6.4) 

Ваши линии 8 и 9 неожиданное поведение не странно. В частности, call t2%print_mytype() происходит после двух окончательных вызовов в заявлении t2=init_mytype(2).

Теперь, откуда происходит финализация из строки 5? И почему -2? Помните, что инициализации нет? -2 - разрешенный результат, если для объекта без назначения. Какой объект завершен?

Посмотрите в функции init_mytype возвращающей результат типа mytype:

function init_mytype(number) 
    type(mytype) :: init_mytype ! No initialization of result 
    integer, intent(in) :: number 

    init_mytype = mytype(number) ! Result finalized before assignment 
    print *, 'init mytype', number 
end function 

В заключение следует сказать, следующие запросы происходят в этой программе:

  • Когда выполняется внутренняя оператор присваивания, переменная завершается после оценки expr и перед определением переменной.
  • Если исполняемая конструкция ссылается на функцию, результат завершается после выполнения самой внутренней исполняемой конструкции, содержащей ссылку.

Как и в сторону, если вы посмотрите на проект Fortran стандарта 2008 года (например, как я сделал, когда я по ошибке скопировали неправильную строку в более ранней ревизии этого ответа) вы можете подумать: почему не являются результаты финализации конструктора структуры? Это должно происходить дважды: один раз прямо в программе и один раз косвенно через звонок до init_mytype. Но мы не видим такого эффекта.

Рассмотрите запрос на устный перевод "How many times are constructed values finalized?" и corrigendum. Результаты конструктора считаются не завершенными, исправляя ошибку в Fortran 2003. Это может иметь значение, поскольку вы спрашиваете о Fortran 2003 (хотя ifort явно реализует новые правила).

+0

ОК в строке 5. Заключительный вопрос находится в строке 8. Объект с nr = 2 в init_mytype копируется в t2 в main, а затем завершается в init_mytype. t2 в основном не завершено, потому что это конец основного. Правильно ли это понимание? – Holger

+0

Есть два объекта с 'nr = 2', да, и это действительно результат' init_mytype', который завершен (другой - 't2' после назначения). Ничто не завершено при достижении «КОНЕЧНОЙ ПРОГРАММЫ». – francescalus

+0

«Если выполнение изображения прекращено, .., путем выполнения. End-program-stmt, сущности, существующие непосредственно перед завершением, не завершены». – francescalus

Смежные вопросы