返回指向 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 访问权限。剩下的问题是 const
和 intent(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 一个(可能)改变引用。
我试图在 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 访问权限。剩下的问题是 const
和 intent(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 一个(可能)改变引用。