Pointers 返回对Ada中成员变量的常量引用

Pointers 返回对Ada中成员变量的常量引用,pointers,ada,Pointers,Ada,我在Ada中有一个包含矩阵的类。我想实现一个函数,将其作为常量访问类型返回,以便能够将其作为只读值获取,但避免不必要的复制 我尝试过返回一个整数的引用,只是为了测试: package Tests_Package is type B is private; function Test(Self : in B) return access constant Integer; private type B is tagged record

我在Ada中有一个包含矩阵的类。我想实现一个函数,将其作为
常量访问
类型返回,以便能够将其作为只读值获取,但避免不必要的复制

我尝试过返回一个整数的引用,只是为了测试:

package Tests_Package is
    type B is private;

    function Test(Self : in B) return access constant Integer;

    private
        type B is tagged
        record
            I : aliased Integer;
        end record;
end Tests_Package;

-------------------------------------------

package body Tests_Package is

    function Test(Self : in B) return access constant Integer is
    begin
        return Self.I'access;
    end Test;

end Tests_Package;
以上内容将无法编译,错误是:
非本地指针不能指向本地对象。

我的问题是:

为什么我会犯这样的错误

是否有任何方法可以实现我想要的,而不使用
未选中的访问


我是否真的需要返回变量的引用,或者Ada编译器可以优化副本?

您会收到错误消息,因为编译器无法保证在实体超出范围/消失后无法保留对该实体的引用


aspect
隐式\u Dereference
有一些技巧,可以解决您的问题。

您会收到错误消息,因为编译器无法保证在实体超出范围/消失后无法保留对它的引用


aspect
隐式解引用有一些技巧,可以解决您的问题。

将参数
设置为别名

function Test(Self : aliased in B) return access constant Integer;

(这将强制通过引用传递参数,

使参数
具有别名

function Test(Self : aliased in B) return access constant Integer;

(强制通过引用传递参数,

安全引用是在Ada 2012中通过结合“Ada 2005中引入的匿名访问类型”和“Ada 2012中引入的隐式解引用方面”引入的,并在此处简要介绍:

丹,在你的特殊情况下

package Tests_Package is

   type Integer_Ref
     (Element : not null access constant Integer) is limited null record with
     Implicit_Dereference => Element;

   type B is tagged private;

   function Test (Self : aliased B) return Integer_Ref;

private

   type B is tagged
      record
         I : aliased Integer := 5;
      end record;

   function Test (Self : aliased B) return Integer_Ref is
      ((Element => Self.I'Access));

end Tests_Package;
它的用法如下:

with Tests_Package;
with Ada.Text_IO;

procedure Main is
   Variable : Tests_Package.B;

   Result   : Integer := 3 + Variable.Test;
begin
   Ada.Text_IO.Put_Line (Result'Img);
end Main;

如果您尝试通过“variable.Test:=1”设置私有变量,您将得到编译时错误,因为您只有整数的只读视图。

安全引用是在Ada 2012中通过结合“Ada 2005中引入的匿名访问类型”和“Ada 2012中引入的隐式引用方面”引入的并在这里简要介绍:

丹,在你的特殊情况下

package Tests_Package is

   type Integer_Ref
     (Element : not null access constant Integer) is limited null record with
     Implicit_Dereference => Element;

   type B is tagged private;

   function Test (Self : aliased B) return Integer_Ref;

private

   type B is tagged
      record
         I : aliased Integer := 5;
      end record;

   function Test (Self : aliased B) return Integer_Ref is
      ((Element => Self.I'Access));

end Tests_Package;
它的用法如下:

with Tests_Package;
with Ada.Text_IO;

procedure Main is
   Variable : Tests_Package.B;

   Result   : Integer := 3 + Variable.Test;
begin
   Ada.Text_IO.Put_Line (Result'Img);
end Main;

如果您尝试通过“variable.Test:=1”设置私有变量,您将得到编译时错误,因为您只有整数的只读视图。

您的代码+我的修改使用GCC 6、7、8和GNAT CE 2016、2017、2018进行编译。不知道区别是什么(当然,您的类型B已标记,因此它仍然是通过引用进行的。哈。)你的代码+我的修改使用GCC 6、7、8和GNAT CE 2016、2017、2018进行编译。不知道区别是什么(当然,你的类型B是有标签的,所以它是通过引用的。哈。)副本可以进行优化。除非您在满足预先指定的定量计时要求方面有明显的失败,否则您不应该担心它。在这种特殊情况下,函数的
Self
参数是按值传递的。这意味着编译器
将创建传递值的
本地副本。当ion返回时,此本地副本不再存在;因此,返回的地址无效。要使其正常工作,可以将此值作为
access
(C/C++中的指针)传递。可以对副本进行优化。除非您在满足预先指定的定量计时要求方面存在明显的失败,否则您不必担心它。在这种特殊情况下,函数的
Self
参数是按值传递的。这意味着编译器
将创建传递值的
本地副本tion返回时,此本地副本不再存在;因此,返回的地址无效。若要使其正常工作,可以将此值作为
access
(C/C++中的指针)传递。