Fortran 使用intent(in)更改子例程参数的指针成员

Fortran 使用intent(in)更改子例程参数的指针成员,fortran,fortran90,fortran2003,Fortran,Fortran90,Fortran2003,为了好玩,我正在用Fortran编写一个稀疏矩阵库,但遇到了一点小麻烦。我有一个与接口矩阵相乘的子程序 subroutine matvec(A,x,y) class(sparse_matrix), intent(in) :: A real(double_precision), intent(in) :: x(:) real(double_precision), intent(inout) :: y(:) {etc.} 这使用了我自己定义的稀疏矩阵类型,其实现并不

为了好玩,我正在用Fortran编写一个稀疏矩阵库,但遇到了一点小麻烦。我有一个与接口矩阵相乘的子程序

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
期间跟踪事件。但是,如果我在矩阵乘法过程中更改
迭代器的状态,并依次更改
A
的状态,编译器将抛出拟合,因为
A
对该子例程有意图(in)

假设我改变周围的事物,而不是定义

type :: sparse_matrix
    type(matrix_iterator), pointer :: iterator
    {etc.}
如果我在矩阵有意图(in)的过程中更改迭代器的状态没有问题,因为指向迭代器的指针的值不会更改;只有存储在该地址的内存受到影响。通过制作一个简化的测试用例来证实这一点,该用例使用GCC编译并运行良好

我认为这是一个合适的修复方法,对吗?或者我应该更改子例程以使A具有意图(inout)?它使用GCC编译的事实并不一定意味着它符合标准,也不意味着它是良好的编程实践

为了与C进行类比,假设我有一个函数
foo(int*const p)
。如果我写

*p = 42;
这是可以的,因为指针的值没有改变,只有存储在指向的地址的数据。另一方面,我不会写字

p = &my_var;

因为它是一个常量指针。

是的,没有问题。实际上,这种做法是众所周知的,例如,在执行引用计数内存管理时使用它,因为定义赋值的右侧是一个
intent(in)
表达式,但您必须能够减少其中的引用计数。

如果您需要迭代器在子例程中变化,让它成为
intent(inout)
可能是个好主意。