2010-10-15 5 views
2

я несколько озадачен следующей программеуказатель в качестве фиктивного аргумента

module test 
    implicit none 

    type TestType 
     integer :: i 
    end type 

contains 
    subroutine foo(test) 
     type (TestType), intent(out) :: test 
     test%i = 5 
    end subroutine 

    subroutine bar(test) 
     type (TestType), intent(out) :: test 
     test%i = 6 
    end subroutine 

end module 

program hello 
    use test 
    type(TestType) :: t 

    call foo(t) 
    print *, t%i 
    call bar(t) 
    print *, t%i 
end program hello 

и его производных. Подробнее об этом позже. Как мы знаем, Fortran передает обычные аргументы в качестве перекрестных ссылок, что означает, что сущность, возникающая в аргументе фиктивного test для обоих foo и bar, представляет собой то же пространство памяти, которое предоставляется в стеке в program hello. Все идет нормально.

Предположим, я определяю в program hellotype(TestType) :: t как указатель и выделяю его.

program hello 
    use test 
    type(TestType), pointer :: t 

    allocate(t) 

    call foo(t) 
    print *, t%i 
    call bar(t) 
    print *, t%i 

    deallocate(t) 
end program hello 

код работает, как и прежде, с той лишь разницей в том, что объект не был выделен в стеке, но в куче.

Предположим теперь, чтобы вернуться к программе стека выделяется и подпрограммой бар вместо определяется как

subroutine bar(test) 
    type (TestType), pointer :: test 
    test%i = 6 
end subroutine 

Программа не компилируется больше, потому что вы должны использовать кучи распределённая версию, чтобы сделать его работу, или, чтобы быть более точным, необходимо передать указатель на подпрограмму, когда подпрограмма определена, чтобы принять указатель в качестве фиктивного аргумента. С другой стороны, если фиктивный аргумент не содержит ключевое слово pointer, подпрограмма будет принимать как указатели, так и не указатели.

Это заставляет меня задуматься ... в чем смысл объявления фиктивного аргумента указателем?

+0

@Rook: Пойдите для этого ... :) –

ответ

4

из comp.lang.fortran Повторно, ответ Тобиас Бернс:

Теперь предположим, чтобы вернуться к программе стека выделяется и подпрограммой бар вместо определяется как

подпрограмма бар (тест) типа (TestType), указатель :: тест тест% я = 6 конца подпрограмма

программа не компилируется любым больше, потому что вы должны использовать кучу распределённой версии, чтобы сделать его работу,

Это не совсем верно: Вы можете не пройти ALLOCATABLE переменной на манекен с атрибутом POINTER. Я думаю, что одна (практическая) причина - , что адрес указателя может уйти, и вы, таким образом, вызовите псевдоним . Формальная причина заключается в том, что ALLOCATABLE просто не является POINTER; Кроме того, стандарт не говорит о куче против стека против статической памяти. И на самом деле локальные массивы [с постоянными границами] будут часто создаваться в статической памяти, а не в стеке (если вы не используете OpenMP или атрибут RECURSIVE). Таким образом, пример вашего «стека» мог бы также быть примером «статической памяти», в зависимости от компилятора и используемых опций .

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

Это также не совсем так. В Fortran 2008 вы можете передать не POINTER, который имеет атрибут TARGET, в манекен указателя, у которого имеет атрибут INTENT (IN). (Pointer намерение является относительно статуса ассоциации указателя , для не-указателя манекенов намерений находятся значениями , хранящихся в переменном.)

Это заставляет меня задаться вопросом ... какой смысл объявлять манекен аргумент указатель?

Ну, если аргумент имеет атрибут POINTER, вы можете выделить и бесплатно целевой указатель, вы можете связать указатель с некоторой целью и т.д. До Fortran 95 не было возможностью иметь ALLOCATABLE фиктивной таким образом, указатель должен был использоваться, если аргумент (фиктивный) должен был быть , выделенный в процедуре.

Если вы можете, вы должны попробовать использовать вместо ALLOCATABLEs чем Pointers - они проще в использовании, не утечку памяти и иметь не представляет проблем псевдонима анализа в компиляторе. С другой стороны, если вы хотите, чтобы для создания, например, связанного списка, вам нужен указатель. (Хотя, для использования кучи , также могут быть использованы в Fortran 2008 * компоненты выделены,.)

*I mean: 
    type t 
     type(t), allocatable :: next 
    end type 

, где компонент того же типа, что и определяемый типа; до F2008 это разрешалось только для указателей, но не для allocatables.

и Р. Мэн

Как мы знаем, Fortran передает обычные аргументы в качестве передачи по ссылке,

Мы знаем, по-видимому, incorectly, затем. В стандарте никогда не указывается, что и, действительно, идет довольно далеко, чтобы избежать такой спецификации. Хотя ваше распространенное заблуждение, оно не было строго точным даже в большинстве старых компиляторов, особенно при включенной оптимизации. Строгая перекрестная ссылка убьет многие общие оптимизации.

С последними стандартами в некоторых случаяхпропускается по ссылке. Стандарт не использует эти слова в своем нормативном тексте, но есть вещи, которые нецелесообразно реализовать с помощью пропущенных ссылок.

Когда вы начинаете входить в такие вещи, как указатели, ошибка при принятии в том, что все передаваемые по ссылке начнут делать себя более очевидным, чем раньше. Вам придется отказаться от этого заблуждения или многих вещей, которые вас смутят.

Я думаю, что другие люди ответили на остальную часть сообщения адекватно. Некоторые также обратились к вышеуказанному пункту, но я хотел подчеркнуть его.

Надеюсь, это ответит на ваш вопрос.

+0

Единственное, что отвечает, это то, что я не понимаю fortran, поскольку я, хотя и сделал. Это уже большой и важный шаг, и я благодарю вас за ваши усилия в этом отношении. –

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