Fortran 使用intent(in)更改子例程参数的指针成员
为了好玩,我正在用Fortran编写一个稀疏矩阵库,但遇到了一点小麻烦。我有一个与接口矩阵相乘的子程序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.} 这使用了我自己定义的稀疏矩阵类型,其实现并不
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)
可能是个好主意。