延长变量的生命周期
Extending a Variable's Lifetime
公平地说,我不能完全确定标题是否正确描述了我遇到的问题,因为它只是反映了我目前对 Ada 的理解。
问题
我有一个功能:
function Make_Option (Title : String) return Access_Option is
O : aliased Option := (
Title_Len => Title'Length,
Title => Title);
begin -- Make_Option
return O'Unrestricted_Access;
end Make_Option;
此函数应该为用户创建一个新的菜单选项,然后可以将其插入菜单(您可能会在 terminal-based 环境中看到的菜单)。你们可能都在叹息,很明显, O
变量将在这个函数的末尾被释放(根据我目前的理解)。因此,在这里使用 Unrestricted_Access
简直是愚蠢,但它反映了我试图完成的结果(因为这段代码确实编译成功)。
Access_Option
定义如下:
type Access_Option is access all Option;
这个想法是,通过访问选项,它又是一个可区分的记录,我们可以将它存储在一个 array-like 结构中(因为 object 本身的大小不同).
毫无疑问,如果我们可以为此使用 Access
属性就好了,因为编译器会确保我们引用的 O
变量的生命周期足够长, 但事实上生命周期只存在于 Make_Option
函数的末尾,我们将看到以下内容:
non-local pointer cannot point to local object
然后我要问的是:我将如何拥有一个为我创建 Access_Option
的函数?这样的事情甚至可能吗,还是我做错了?澄清一下,我想做的是创建一种巧妙的方法来使用对不同记录的引用来填充数组,然后我可以取消引用并使用它。
思考过程
我个人并没有尝试过太多的东西,更多的是思考可能对问题合理的解决方案。而且,坦率地说,与其疯狂地使用临时解决方案,不如有一个也适用于 large-scale 应用程序的解决方案,而不会将代码库搞得一团糟。
您是否可以使用某种 object queue 来处理它? Ada 甚至会自动释放资源吗?啊。我很困惑。
事实上,是否有可能以某种方式将 O
变量置于释放范围之外,然后稍后手动释放它?
不要那样做。
有两个备选方案:
1) 使用 Ada.Containers.Indefinite_Vectors 而不是普通数组。
2) 给你的记录判别式一个默认值。然后你可以将它存储在一个普通数组中。
鉴于您在上面显示的示例,一种更简单的方法是简单地制作一个 Unbounded_String:
的数组
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_Io;
procedure Str_Arrays is
type Arr is array(1..10) of Unbounded_String;
A : Arr;
begin
for S of A loop
S := To_Unbounded_String("Hello World!");
end loop;
for S of A loop
Put_Line(To_String(S));
end loop;
end Str_arrays;
您似乎在重新发明有界字符串。备选方案包括
- 使用
Ada.Strings.Bounded.Generic_Bounded_Length
的实例化
- 使用
Ada.Strings.Unbounded
- 使用不定容器 (
Ada.Containers.Indefinite_*
) 来保存类型 String
公平地说,我不能完全确定标题是否正确描述了我遇到的问题,因为它只是反映了我目前对 Ada 的理解。
问题
我有一个功能:
function Make_Option (Title : String) return Access_Option is
O : aliased Option := (
Title_Len => Title'Length,
Title => Title);
begin -- Make_Option
return O'Unrestricted_Access;
end Make_Option;
此函数应该为用户创建一个新的菜单选项,然后可以将其插入菜单(您可能会在 terminal-based 环境中看到的菜单)。你们可能都在叹息,很明显, O
变量将在这个函数的末尾被释放(根据我目前的理解)。因此,在这里使用 Unrestricted_Access
简直是愚蠢,但它反映了我试图完成的结果(因为这段代码确实编译成功)。
Access_Option
定义如下:
type Access_Option is access all Option;
这个想法是,通过访问选项,它又是一个可区分的记录,我们可以将它存储在一个 array-like 结构中(因为 object 本身的大小不同).
毫无疑问,如果我们可以为此使用 Access
属性就好了,因为编译器会确保我们引用的 O
变量的生命周期足够长, 但事实上生命周期只存在于 Make_Option
函数的末尾,我们将看到以下内容:
non-local pointer cannot point to local object
然后我要问的是:我将如何拥有一个为我创建 Access_Option
的函数?这样的事情甚至可能吗,还是我做错了?澄清一下,我想做的是创建一种巧妙的方法来使用对不同记录的引用来填充数组,然后我可以取消引用并使用它。
思考过程
我个人并没有尝试过太多的东西,更多的是思考可能对问题合理的解决方案。而且,坦率地说,与其疯狂地使用临时解决方案,不如有一个也适用于 large-scale 应用程序的解决方案,而不会将代码库搞得一团糟。
您是否可以使用某种 object queue 来处理它? Ada 甚至会自动释放资源吗?啊。我很困惑。
事实上,是否有可能以某种方式将 O
变量置于释放范围之外,然后稍后手动释放它?
不要那样做。
有两个备选方案:
1) 使用 Ada.Containers.Indefinite_Vectors 而不是普通数组。
2) 给你的记录判别式一个默认值。然后你可以将它存储在一个普通数组中。
鉴于您在上面显示的示例,一种更简单的方法是简单地制作一个 Unbounded_String:
的数组with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_Io;
procedure Str_Arrays is
type Arr is array(1..10) of Unbounded_String;
A : Arr;
begin
for S of A loop
S := To_Unbounded_String("Hello World!");
end loop;
for S of A loop
Put_Line(To_String(S));
end loop;
end Str_arrays;
您似乎在重新发明有界字符串。备选方案包括
- 使用
Ada.Strings.Bounded.Generic_Bounded_Length
的实例化
- 使用
Ada.Strings.Unbounded
- 使用不定容器 (
Ada.Containers.Indefinite_*
) 来保存类型String