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

时间:2013-11-22 18:12:22

标签: 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.}

这使用了我自己定义的稀疏矩阵类型,其实现并不重要。现在,如果A包含名为iterator的对象,我可以使事情变得更好并且代码更少:

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

存储了一些在matvec期间跟踪事物的变量。但是,如果我在矩阵乘法期间更改iterator的状态并依次改变状态A,编译器将抛出拟合,因为A具有该子例程的意图(in)。 / p>

假设我改变了一些事情,而是定义

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;

因为它是一个常量指针。

1 个答案:

答案 0 :(得分:2)

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