Fortran 中复制赋值和构造函数之间的冲突
Clash between copy assignment and constructor in Fortran
我有以下产生分段错误的代码。它确实抱怨
forrtl: severe (408): fort: (7): Attempt to use pointer TT when it is not associated with a target
现在我很确定原因是什么,即它正在尝试访问我的 copy
赋值例程,而我只是在尝试初始化对象。
通过注释掉 generic :: assignment(=) => copy
它工作正常!
我正在编译代码如下:(IFORT版本19.0.3)
ifort -O0 -debug full -check all -traceback -g -C -CB -CU -CA -fpp filaname.f90
运行 ./a.out
module md
implicit none
type T_TEST
integer :: ii
contains
procedure, pass(this) :: COPY
generic :: assignment(=) => copy
end type
interface t_test
module procedure init
end interface t_test
type(t_test) , allocatable :: tt
contains
function init( size )
integer, intent(in) :: size
type(t_test) , allocatable :: init
allocate( init )
init% ii = size
end function
subroutine copy(this, old )
class(t_test), intent(out) ::this
type(t_test), intent(in) :: old
this% ii = old% ii
end subroutine
end module md
program t_Testprogram
use md
implicit none
tt = t_test( 100 )
end program t_Testprogram
原因是重载赋值 copy
不支持可分配的左侧。所以当 this% ii = old% ii
中使用 this
的值时,它实际上不存在并且使用了空指针。但我同意英特尔的错误信息令人困惑甚至不正确。
自动左侧(重新)分配仅适用于内部分配,不适用于用户定义的分配。在用户定义的那些中,您必须自己编写确切的行为。而且您没有为未分配的左侧指定任何内容。
这对我有用:
type T_TEST
integer :: ii
end type
interface assignment(=)
procedure copy
end interface
subroutine copy(this, old )
class(t_test), allocatable, intent(out) ::this
type(t_test), intent(in) :: old
if (.not.allocated(this)) allocate(this)
this% ii = old% ii
end subroutine
或者您可以先分配对象(这就是我在这里要做的,因为 gfortran 似乎不喜欢基于可分配属性的通用解析 - F08 功能)。
allocate(tt)
tt = t_test( 100 )
看来你在想,仅仅因为构造函数有它的结果变量"marked" allocatable
,它就会为你分配左边的赋值。 并非如此。它唯一做的就是将自己的结果分配为临时变量。然后将此结果分配到 tt = t_test()
中,然后自动释放。
记住,结果变量不与赋值的左侧相同。结果可以用在许多不同类型的表达式中,而不仅仅是在赋值中。可以传递给子程序,可以用在算术表达式中,可以打印...
你的构造函数可以只是
function init( size )
integer, intent(in) :: size
type(t_test) :: init
init% ii = size
end function
结果将完全相同。没有理由让它可分配,它只会使它复杂化,但丝毫不会改变结果。
也许您正在尝试遵循一些 C++ RAII 原则,但请记住,C++ 根本不是 Fortran。
我有以下产生分段错误的代码。它确实抱怨
forrtl: severe (408): fort: (7): Attempt to use pointer TT when it is not associated with a target
现在我很确定原因是什么,即它正在尝试访问我的 copy
赋值例程,而我只是在尝试初始化对象。
通过注释掉 generic :: assignment(=) => copy
它工作正常!
我正在编译代码如下:(IFORT版本19.0.3)
ifort -O0 -debug full -check all -traceback -g -C -CB -CU -CA -fpp filaname.f90
运行 ./a.out
module md
implicit none
type T_TEST
integer :: ii
contains
procedure, pass(this) :: COPY
generic :: assignment(=) => copy
end type
interface t_test
module procedure init
end interface t_test
type(t_test) , allocatable :: tt
contains
function init( size )
integer, intent(in) :: size
type(t_test) , allocatable :: init
allocate( init )
init% ii = size
end function
subroutine copy(this, old )
class(t_test), intent(out) ::this
type(t_test), intent(in) :: old
this% ii = old% ii
end subroutine
end module md
program t_Testprogram
use md
implicit none
tt = t_test( 100 )
end program t_Testprogram
原因是重载赋值 copy
不支持可分配的左侧。所以当 this% ii = old% ii
中使用 this
的值时,它实际上不存在并且使用了空指针。但我同意英特尔的错误信息令人困惑甚至不正确。
自动左侧(重新)分配仅适用于内部分配,不适用于用户定义的分配。在用户定义的那些中,您必须自己编写确切的行为。而且您没有为未分配的左侧指定任何内容。
这对我有用:
type T_TEST
integer :: ii
end type
interface assignment(=)
procedure copy
end interface
subroutine copy(this, old )
class(t_test), allocatable, intent(out) ::this
type(t_test), intent(in) :: old
if (.not.allocated(this)) allocate(this)
this% ii = old% ii
end subroutine
或者您可以先分配对象(这就是我在这里要做的,因为 gfortran 似乎不喜欢基于可分配属性的通用解析 - F08 功能)。
allocate(tt)
tt = t_test( 100 )
看来你在想,仅仅因为构造函数有它的结果变量"marked" allocatable
,它就会为你分配左边的赋值。 并非如此。它唯一做的就是将自己的结果分配为临时变量。然后将此结果分配到 tt = t_test()
中,然后自动释放。
记住,结果变量不与赋值的左侧相同。结果可以用在许多不同类型的表达式中,而不仅仅是在赋值中。可以传递给子程序,可以用在算术表达式中,可以打印...
你的构造函数可以只是
function init( size )
integer, intent(in) :: size
type(t_test) :: init
init% ii = size
end function
结果将完全相同。没有理由让它可分配,它只会使它复杂化,但丝毫不会改变结果。
也许您正在尝试遵循一些 C++ RAII 原则,但请记住,C++ 根本不是 Fortran。