我用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)
表达式,但您必须能够减少其中的引用计数。