Я пишу библиотеку разреженных матриц на Фортране для развлечения, но столкнулся с небольшой загвоздкой. У меня есть подпрограмма для умножения матриц с интерфейсом
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;
потому что это постоянный указатель.
intent(inout)
. - person Kyle Kanos   schedule 22.11.2013