返回指向 intent(in) 参数的指针

Returning pointer to intent(in) argument

我试图在 classes 的上下文中更好地理解 C/C++ 中的 const 和 Fortran 中的 intent(in) 之间的区别。

C++: 如果我 const 成员函数的隐式 this 参数并且我 return 引用 this 的成员,这些引用必须是 const T*。 所以 const 不仅适用于函数调用的范围,而且还扩展到该函数调用中“创建”的所有引用。

Fortran:如果我intent(in)成员函数的this参数,intent(in)只适用于成员函数的作用域.我不能在成员函数内部改变 this,但我可以 return 引用并在外部修改 this

如果我在 Fortran 和 C++ 中有以下或多或少等效的计数器 class 代码来测试它,它似乎是正确的。

#include <iostream>


class Counter {
    int val{};

public:
    auto next()
    {
        return val++;
    };

    const auto raw() const
    {
        const auto ptr = &val;
        return ptr;
    };
};

int main()
{
    Counter c{};
    std::cout << c.next() << "\n";
    std::cout << c.next() << "\n";

    auto ptr = c.raw();
    // does not compile, as it is expected
    *ptr = 0;
    std::cout << c.next() << "\n";

    return 0;
}
module counter_mod
    implicit none(type, external)
    private
    public :: Counter_t

    type :: Counter_t
        private
        integer :: val = 0
    contains
        procedure :: next
        procedure :: raw
    end type

contains

    integer function next(this)
        class(Counter_t), intent(inout) :: this
        next = this%val
        this%val = this%val + 1
    end function

    function raw(this) result(res)
        class(Counter_t), target, intent(in) :: this
        integer, pointer :: res
        ! This would be forbidden
        ! this%val = 5
        res => this%val
    end function
end module

program test_raw
    use counter_mod, only: Counter_t
    implicit none(type, external)

    type(Counter_t), target :: c
    integer, pointer :: ptr

    write(*, *) c%next()
    write(*, *) c%next()

    ptr => c%raw()
    ptr = 0
    write(*, *) c%next()
end program

在c++中你不需要return一个const pointer你可以简单地return一个const reference。这是典型的 getter 实现,例如:

const方法表示实例属性不会被该方法修改。

class Counter {
    int val{};

public:
    auto next()
    {
        return val++;
    };

    const int &getVal const
    {
        return val;
    };
};

在上面的示例中,getter 也可以 return val 的副本。 (在那种情况下不需要 returning const 引用)。

在阅读了关于我问题的 C++ 部分的评论和答案并参考了 Fortran 2008 标准之后,我想我可以回答我自己的问题:

C++: 不可能(没有像 const_cast 这样的技巧)创建 T* 指针或 T& 对类型 T 变量的 const T 引用。 pointers/references 也必须是 const。 因此:如果 this 是我们成员函数的 const 参数,我们不允许 return 非 const 指针或引用。

int& getVal() const {return val;};
int* getVal() const {return &val;};

两者都无法编译。因此,通过将 this 声明为 const,我们可以为我们的成员提供 read-only 访问权限。 (感谢@Jean-Marc Volle,我将使用第一个版本。)

Fortran: Fortran 中的根本问题是,没有指向 const (const T*) 的指针,而只有 const 指针 (T* const)。因此,不可能通过指向某个类型的组件(C++ 中 class 的成员)的指针来提供 read-only 访问权限。剩下的问题是 constintent(in) 之间的区别,以及是否有可能 return 对 intent(in) 的对象(或其组件)的可能变异引用。 =32=]

在 Fortran 2008 标准 5.3.10 中 它说:

The INTENT (IN) attribute for a nonpointer dummy argument specifies that it shall neither be defined nor become undefined during the invocation and execution of the procedure. The INTENT (IN) attribute for a pointer dummy argument specifies that during the invocation and execution of the procedure its association shall not be changed except that it may become undefined if the target is deallocated other than through the pointer (16.5.2.5).

如果我解释正确,不允许改变 intent(in) 对象,但可以 return 一个(可能)改变引用。