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



我用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.}

其存储在CCD_ 3期间跟踪事物的一些变量。但是,如果在矩阵乘法过程中更改iterator的状态,进而更改A的状态,编译器将抛出拟合,因为A有意(in)该子例程。

假设我改变了现状,转而定义

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

如果在矩阵具有intent(in)的过程中更改迭代器的状态,这是没有问题的,因为迭代器指针的值不会改变;只有存储在该地址的存储器受到影响。这一点通过制作一个简化的测试用例得到了证实,该用例使用GCC编译和运行都很好。

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

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

*p = 42;

这是可以的,因为指针的值不会改变,只有存储在所指向地址的数据。另一方面,我不能写

p = &my_var;

因为它是一个常量指针。

是的,可以。事实上,这种做法是众所周知的,例如在进行引用计数内存管理时也会使用它,因为定义赋值的右手边是intent(in)表达式,但您必须能够减少其中的引用计数。

最新更新