当我初始化函数或子例程中的对象并尝试返回它时,在构造函数中设置的指针成员似乎变得未定义(尽管我可能会误解正在发生的事情)。
我想准确理解这里发生了什么,如果可能的话,如何在构造函数中初始化指针,然后在保留指针的同时从函数或子例程返回对象。
MWE:
#include <vector>
#include <iostream>
template<class T>class LinAlg
{
private:
std::vector<T> mVector;
int mSize;
public:
LinAlg(int size);
T & operator[](int i);
T const & operator[] (int i)const;
};
template<class T> LinAlg<T>::LinAlg(int size)
{
mSize = size;
std::vector<T> mVector;
for (int i=0; i<mSize; i++)
{
mVector.push_back(0);
}
}
template<class T> T & LinAlg<T>::operator[](int i)
{
return mVector[i];
}
template<class T> T const& LinAlg<T>::operator[](int i)const
{
return mVector[i];
}
int main()
{
LinAlg<double> vec(2);
vec[0] = 1.0;
vec[1] = 1.0;
for(int i=0; i<2; i++)
{
std::cout << vec[i] << '\n';
}
return 0;
}
使用gfortran 5.4.0,
program mwe
implicit none
type a
integer var
end type a
type b
type(a), pointer :: elt
end type b
interface b
procedure construct_b
end interface
type(b) val_func, val_sub
val_func = get_new_b(52)
write(*,*) 'using function: ', val_func%elt%var
call new_b(val_sub, 55)
write(*,*) 'using subroutine: ', val_sub%elt%var
contains
function construct_b(elt) result(r)
class(a), target, intent(in) :: elt
type(b) r
r%elt => elt
end function
function get_new_b(n) result(r)
integer, intent(in) :: n
type(b) r
type(a) elt
elt = a(n)
r = b(elt)
write(*,*) 'get_new_b: ', r%elt%var
end function
subroutine new_b(r, n)
type(b), intent(inout) :: r
integer, intent(in) :: n
type(a) elt
elt = a(n)
r = b(elt)
write(*,*) 'new_b: ', r%elt%var
end subroutine
end program mwe
我期望的输出是:
$ gfortran -o mwe.x mwe.f90
$ ./mwe.x
get_new_b: 52
using function: 127919104
new_b: 55
using subroutine: 127919104
答案 0 :(得分:2)
在get_new_b
程序中,您正在执行:
type(a) elt
elt = a(n)
r = b(elt)
这意味着您正在函数内部创建局部变量elt
,然后您使用此变量调用constructor_b
(通过b
接口)。在constructor_b
内,会发生什么:
type(b) r
r%elt => elt
即,您创建了一个新的type(b)
变量,并在其elt
字段与您传入的变量elt
之间执行指针关联。
问题是:您作为参数传递的实际参数elt
是 local 到函数get_new_b
的范围。当控件返回主程序时,指针的目标(在函数内创建的elt
变量)不再存在,指针就会“悬空”。
你永远不应该有一个指向超出范围的变量的指针。
在您提供的代码中,拥有可分配组件更有意义。只有当你想将它指向其他现有变量时才会有一个指针组件(其内存由你的代码的其他部分管理,而不是由类型本身管理)。
但是如果指针是你想要的,那么确保它的目标永远不会在带有指针组件的变量之前被定义。