【问题标题】:Does the locally initialized variable rule also apply for pointers?本地初始化的变量规则是否也适用于指针?
【发布时间】:2014-01-30 17:54:51
【问题描述】:

我知道在初始化本地声明的变量时应该小心(reference)。

!这是错误的方式 (声明时初始化的局部变量具有隐式保存属性。)

     real function kinetic_energy(v)
     real, dimension(:), intent(in) :: v
     real :: ke = 0.0
     end function kinetic_energy

!这是正确的方法

     real function kinetic_energy(v)
     real, dimension(:), intent(in) :: v
     real :: ke
     ke = 0.
     end function kinetic_energy

我想知道我们是否也有类似的指针。

     real function kinetic_energy(v)
     real, dimension(:), intent(in) :: v
     real, pointer :: ke => null()
     end function kinetic_energy

     real function kinetic_energy(v)
     real, dimension(:), intent(in) :: v
     real, pointer :: ke
     nullify(ke)
     end function kinetic_energy

声明时无效的指针变量将被视为保存属性!

感谢您提供有用的信息。我已经读过,根据你所说的,总是初始化指向 NULL 的指针,这可能是完全错误的说法。例如,我不应该在我的子例程中初始化我的本地指针变量! (如果它们在子例程的每个入口处分配给新的大小)我是对的!!!

 real function kinetic_energy(v)   
 real, dimension(:), intent(in) :: v   
 !local variables
 real, dimension(:), pointer :: ke => null()
 integer :: n
 !
 n=size(v,1)   
 allocate(ke(n))   
 !make a copy   
 ke=v   
 !do some computation ...   
 end function kinetic_energy

【问题讨论】:

    标签: fortran fortran90 gfortran fortran95


    【解决方案1】:

    指针和非指针的情况实际上几乎相同。 @francescalus 是正确的,规则 5.3.16.1 确实谈到了指针目标变得未定义的可能性,但这在这里并不重要。当然,如果保存的指针指向的东西是短暂的,那么在目标不存在后它就无效了,但这很明显。

    但是显式初始化的语义对于指针和非指针是相同的。它暗示了save 属性。这意味着在过程调用之间保留值或指针关联,因此初始化只进行一次(您的版本 1 和 3)。如果要在每次过程调用时分配所需的值,则必须使用正常的可执行分配,而不是显式初始化表达式或其他可执行语句(您的版本 2 和 4)。


    编辑:

    关于您的新(最后一个)示例,对我来说,这看起来像是使用allocatable 而不是pointer 的地方。它们永远不会未定义,而是以 not allocated 开头。

    如果你需要它是一个指针,如果你不测试它的关联状态,它仍然不必在分配之前被取消。您始终可以在可执行代码的开头使用nullify()

    【讨论】:

    • 感谢您提供此信息。但如果你能再次帮助我,那就太好了。我读过always initialize pointers to NULL,根据你所说的,这可能是完全错误的说法。例如,我不应该在我的子程序中初始化我的本地指针变量! (如果它们在子例程的每个入口处分配给新的大小)
    • 那个语句的意思是你应该在子程序的开头使用nullify语句或者p => null(),仅此而已。此外,并非您在某处读到的所有内容都一定是正确的。当然,如果立即分配指针,则不必事先将其无效。
    • @user3244667 也可能是关于始终default 初始化指针组件的建议。这比在子程序中初始化(有很多反例)要好得多。
    • 没错。或者在可执行指针赋值语句中执行此操作。几乎可以肯定不在声明中。
    • 还可以考虑尽可能使用allocatables 而不是指针。它们总是自动初始化为not allocated
    【解决方案2】:

    F2008标准中提到隐含SAVE属性的部分(5.2.3)不区分POINTER或not-POINTER的情况。

    顺便说一句,虽然指针会获取属性,但指针SAVE 的含义略有不同:

    [...] 除非它是一个指针并且它的目标变得未定义

    请参阅@VladimirF 的回答(这促使我在此处澄清)了解更多信息。但是请注意,错误地认为指针空初始化在作用域的每个条目上都被取消可能比认为变量每次都分配为零更糟糕:如果 ke 具有未定义的指针关联,则简单地测试 ASSOCIATED(ke) 是非标准的状态。

    转到您的示例,您有“错误的方式”和“正确的方式”错误的方式:“错误的方式”是正确的初始化方式,而“正确的方式”是错误的初始化方式。也就是说,只有在第一种情况下才会发生初始化。

    根据问题更新进行编辑:

    具有pointer 属性的变量与没有初始化的变量没有什么不同:如果变量具有显式初始化,它会获取save 属性。如果你想让一个变量没有这个属性,那么它就不能被显式初始化。 [这是对原始问题的比我以前可能有的更明确的答案。]

    有关于始终“初始化”指针的建议。用 MR&C 的话来说,他们通常有很好的建议:

    我们的建议是对所有指针进行如此初始化,以减少因意外使用未定义指针而产生奇怪影响的风险。这也有助于编写避免内存泄漏的代码。

    不过,这里的“初始化”确实包括“在子例程的早期无效”以及显式初始化。

    但是,这不是必需的。如果指针要与其他东西相关联,则不需要(但可以)首先将其无效。即使是好的建议也不能成为逃避谨慎的借口。

    但它仍然成立,如果save 不好,那么显式初始化也不好。

    此外,您可能会看到有关它对具有默认初始化的派生类型的指针组件有益的建议。这是明智的建议。

    【讨论】:

    • 对不起,我的错误。我已经更正了问题中的代码,现在是上面的初始化问题。
    • 我以为这就是你的意思 - 实际上我最初并没有注意到这个问题 - 我已经删除了答案的那部分。
    猜你喜欢
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多