指针

当我们需要创建一些动态数据类型的时候,例如链表,二叉树,这时候就需要指针。

指向变量的指针

使用pointer关键字可以创建一个指针,使用=>可以指向对应的目标,此时要求被指的对象具有target属性,或者pointer属性

integer,target::x
integer,pointer::px=>null() !提供了null()指针将其指向空
px=>x
x=3
write(*,*)x,px
px=5
write(*,*)x,px

Fortran中的指针并不是获取地址,而是获取目标的引用。你可以理解成pxx的一个别名,当我们修改pxx带来的效果是一样的。

  • Fortran中之所以要求被指针指向的变量具有target或者pointer属性是为了防止在优化过程中这个变量被优化掉

指向数组的指针

指向数组的指针需要给定维度,但是不能指定大小,只能用:表示。

integer,target::x(10)
integer,pointer::px(:) !只能定义为(:)
px=>x
x=3
write(*,*)px
px=>x(1:10:2) !可以指向数组切片
write(*,*)px
!px=>x([1,2,3])!错误,不能指向数组下标,因为数组下标返回的是临时数组

从这里可以看出Fortran中的数组在定义的时候是连续的,但是在使用的过程中不一定是连续的

指针分配内存

我们也可以为指针分配内存,它和可分配数组的使用类似

integer,pointer::p
integer,pointer::pa(:,:)
allocate(p) !分配一个标量
allocate(pa(10,10))!分配一个数组
deallocate(p) !释放
deallocate(pa)
  • 需要注意的是,在使用函数的时候,作为局部变量,可分配变量离开了作用域会自动释放,但是指针不会

使用associated可以查看指针的关联属性

integer,pointer::pa(:)
integer,allocatable,target::a(:)
allocate(a(3),source=[1,2,3])
pa=>a
write(*,*)associated(pa) !检查pa是否被关联
write(*,*)associated(pa,a)!检查pa是否和a关联

内存泄漏

如果对指针进行了分配,但是同时有用它指向了其他的内存,那么就会出现内存泄漏。

integer,pointer::pa(:)
integer,target::a(3)
allocate(pa(3))
pa=[1,2,3]
a=[4,5,6]
pa=>a !内存泄漏
write(*,*)pa
write(*,*)a
  • pa分配的内存没有其他的指针指向它,所以我们再无法访问到,但是它同时又没有被释放

指针悬垂

而另一种情况就是指针指向的内存被释放了,但是我们还是继续使用该指针,这种情况称为指针悬垂。

integer,pointer::pa(:)
integer,allocatable,target::a(:)
allocate(a(3),source=[1,2,3])
pa=>a
write(*,*)pa
deallocate(a)!pa现在指向了一块被释放的内存
write(*,*)pa 

所以,在对应的操作之后,我们需要同时将指针置空,有两种语法。

! 1.
nullify(pa)
! 2.
pa=>null()

例如具有allocatable属性的局部变量,出了作用域会被自动释放,如果用指针指向它,也会造成指针悬垂

关联(associate)

Fortran2003中引入了associate语句,可以简化在代码编写过程中的临时变量问题,基本的语法是

integer::point(3)
integer::l
point=[1,2,3]
associate(x=>point(1),y=>point(2),z=>point(3))
l=x**2+y**2+z**2
end associate

需要注意的是,此时,如果x=>p的右边是变量,那么x相当于是p的别名,修改了xp也会随之改变。如果右边是表达式,那么相当于自动创建一个临时变量。此时其中的变量不需要额外的声明

integer::a(10)
integer::i
a=[(i,i=1,10)]
associate(odd=>a(1:10:2),x=>2*2) !前者为引用,后者为直接创建的临时变量
    odd=odd+x
end associate
write(*,*)a
  • 当我们具有一些比较层数比较深的自定义类型的时候,在代码中使用associate会大大提高代码的可读性
associate(px=>this%particle%x,py=>this%particle%y)
    dis=px**2+py**2
end associate
  • 同一个语句中不能连续定义
associate(x=>point(1),x2=>x*x ) !错误
end associate

需要改成

associate(x=>point(1))
associate(x2=>x*x)
end associate
end associate

这是associate结构的不足之处