изменение членов указателя аргумента подпрограммы с намерением (в)

Я пишу библиотеку разреженных матриц на Фортране для развлечения, но столкнулся с небольшой загвоздкой. У меня есть подпрограмма для умножения матриц с интерфейсом

subroutine matvec(A,x,y)
    class(sparse_matrix), intent(in) :: A
    real(double_precision), intent(in) :: x(:)
    real(double_precision), intent(inout) :: y(:)
    {etc.}

Здесь используется тип разреженной матрицы, который я определил сам, реализация которого не важна. Теперь я могу сделать вещи лучше и писать намного меньше кода, если A содержит объект с именем iterator:

type :: sparse_matrix
    type(matrix_iterator) :: iterator
    {etc.}

в котором хранится несколько переменных, которые отслеживают события во время matvec. Но если я изменю состояние iterator и, в свою очередь, состояние A во время матричного умножения, компилятор выдаст ошибку, потому что A имеет намерение (in) для этой подпрограммы.

Предположим, я меняю вещи и вместо этого определяю

type :: sparse_matrix
    type(matrix_iterator), pointer :: iterator
    {etc.}

Это не проблема, если я изменяю состояние итератора во время процедуры, в которой матрица имеет намерение (в), потому что значение указателя на итератор не меняется; затрагивается только память, хранящаяся по этому адресу. Это подтверждается созданием сокращенного тестового примера, который прекрасно компилируется и работает с использованием GCC.

Правильно ли я считаю, что это подходящее решение? Или я должен изменить подпрограмму так, чтобы у A было намерение (inout)? Тот факт, что он скомпилирован с помощью GCC, не обязательно означает его соответствие стандарту и не означает, что это хорошая практика программирования.

Чтобы провести аналогию с C, предположим, что у меня есть функция foo(int* const p). Если бы я написал

*p = 42;

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

p = &my_var;

потому что это постоянный указатель.


person korrok    schedule 22.11.2013    source источник
comment
Если вам нужно, чтобы итератор изменялся в подпрограмме, вероятно, было бы неплохо сделать его intent(inout).   -  person Kyle Kanos    schedule 22.11.2013


Ответы (1)


Да, это хорошо. На самом деле эта практика хорошо известна и используется, например, при управлении памятью с подсчетом ссылок, потому что правая часть определенного присваивания представляет собой выражение intent(in), но вы должны иметь возможность уменьшить счетчик ссылок в нем.

person Vladimir F    schedule 22.11.2013