指向包含可分配数组的派生类型的指针
Pointer to derived type that contains allocatable array
一般来说,我想重命名通过子例程参数传递的派生类型中的可分配变量。用 'derived%type_xx' 写所有东西并不是那么愉快。此外,我不想花费额外的内存将派生类型的值复制到新变量,这会占用新分配的内存。此外,我知道可分配数组比指针更受青睐,原因有很多。我尝试定义指向可分配变量的指针,但失败了。我尝试这样做是因为我想简化我的代码,既要可读又不要太长。我想知道是否有办法实现目标?谢谢
演示代码如下:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1) :: input
input%longname_1 = input%longname_1 + input%longname_2 ! Use one line to show what I mean
END SUBROUTINE
失败的是:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1),TARGET :: input
REAL,POINTER :: a => input%longname_1 &
& b => input%longname_2
a = a + b ! much better for reading
END SUBROUTINE
这似乎是一个小问题,但我希望以后阅读我的代码时不会太痛苦。那么最好的选择是什么?非常感谢。
您可以使用 ASSOCIATE 构造将简单名称与更复杂的指示符或表达式相关联。
您还可以将派生类型的子对象用作执行该操作的过程的实际参数。
您的指针方法失败,因为您的等级不匹配 - 您试图将标量指针与数组目标相关联。如果您的过程的显式接口在调用作用域中不可用,您也可能会遇到问题。具有 TARGET 属性的虚拟参数的过程需要显式接口。
为这种简单的名称别名使用指针可能会降低编译器优化代码的能力。应该首选类似 ASSOCIATE 的内容。
更新: @IanH 发表评论后,我回去检查:关于您的代码失败的原因,我是完全错误的。正如他在回答中指出的那样,主要问题是指针和目标必须具有相同的等级,因此您必须将 a
和 b
声明为:
real, pointer :: a(:), b(:)
其次,在您实际将这些指针指向目标之前,必须先分配目标。这是一个有效的例子:
program allocatable_target
implicit none
type :: my_type
integer, allocatable :: my_array(:)
end type my_type
type(my_type), target :: dummy
integer, pointer :: a(:)
allocate(dummy%my_array(10))
a => dummy%my_array
a = 10
print *, dummy%my_array
end program allocatable_target
如果您有兼容 Fortran 2003 的编译器,则可以使用 associate
——它专门用于解决此类问题。这是一个例子:
program associate_example
implicit none
type :: my_type
integer, allocatable :: long_name_1(:), long_name_2(:)
end type my_type
type(my_type) :: input
integer :: i
allocate(input%long_name_1(100), input%long_name_2(100))
associate (a=>input%long_name_1, b=>input%long_name_2)
a = (/ (i, i = 1, 100, 1) /)
b = (/ (2*i+4, i = 1, 100, 1) /)
a = a + b
end associate
print *, input%long_name_1
end program associate_example
在 associate
块中,您可以使用 a
和 b
作为声明的较长命名变量的缩写形式。
但除此之外,我建议您使用具有正确代码完成功能的编辑器,这样长变量名就不再是什么大问题了。目前我正在试用 Atom 并且对此非常满意。但是我已经使用 vim
很长一段时间了。
一般来说,我想重命名通过子例程参数传递的派生类型中的可分配变量。用 'derived%type_xx' 写所有东西并不是那么愉快。此外,我不想花费额外的内存将派生类型的值复制到新变量,这会占用新分配的内存。此外,我知道可分配数组比指针更受青睐,原因有很多。我尝试定义指向可分配变量的指针,但失败了。我尝试这样做是因为我想简化我的代码,既要可读又不要太长。我想知道是否有办法实现目标?谢谢
演示代码如下:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1) :: input
input%longname_1 = input%longname_1 + input%longname_2 ! Use one line to show what I mean
END SUBROUTINE
失败的是:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1),TARGET :: input
REAL,POINTER :: a => input%longname_1 &
& b => input%longname_2
a = a + b ! much better for reading
END SUBROUTINE
这似乎是一个小问题,但我希望以后阅读我的代码时不会太痛苦。那么最好的选择是什么?非常感谢。
您可以使用 ASSOCIATE 构造将简单名称与更复杂的指示符或表达式相关联。
您还可以将派生类型的子对象用作执行该操作的过程的实际参数。
您的指针方法失败,因为您的等级不匹配 - 您试图将标量指针与数组目标相关联。如果您的过程的显式接口在调用作用域中不可用,您也可能会遇到问题。具有 TARGET 属性的虚拟参数的过程需要显式接口。
为这种简单的名称别名使用指针可能会降低编译器优化代码的能力。应该首选类似 ASSOCIATE 的内容。
更新: @IanH 发表评论后,我回去检查:关于您的代码失败的原因,我是完全错误的。正如他在回答中指出的那样,主要问题是指针和目标必须具有相同的等级,因此您必须将 a
和 b
声明为:
real, pointer :: a(:), b(:)
其次,在您实际将这些指针指向目标之前,必须先分配目标。这是一个有效的例子:
program allocatable_target
implicit none
type :: my_type
integer, allocatable :: my_array(:)
end type my_type
type(my_type), target :: dummy
integer, pointer :: a(:)
allocate(dummy%my_array(10))
a => dummy%my_array
a = 10
print *, dummy%my_array
end program allocatable_target
如果您有兼容 Fortran 2003 的编译器,则可以使用 associate
——它专门用于解决此类问题。这是一个例子:
program associate_example
implicit none
type :: my_type
integer, allocatable :: long_name_1(:), long_name_2(:)
end type my_type
type(my_type) :: input
integer :: i
allocate(input%long_name_1(100), input%long_name_2(100))
associate (a=>input%long_name_1, b=>input%long_name_2)
a = (/ (i, i = 1, 100, 1) /)
b = (/ (2*i+4, i = 1, 100, 1) /)
a = a + b
end associate
print *, input%long_name_1
end program associate_example
在 associate
块中,您可以使用 a
和 b
作为声明的较长命名变量的缩写形式。
但除此之外,我建议您使用具有正确代码完成功能的编辑器,这样长变量名就不再是什么大问题了。目前我正在试用 Atom 并且对此非常满意。但是我已经使用 vim
很长一段时间了。