String 存储字符串引用 问题

String 存储字符串引用 问题,string,reference,ada,String,Reference,Ada,有多种方法可以存储字符串引用,那么在示例代码中您将如何进行存储呢?当前的问题是存储对字符串的访问,因为它导致非本地指针无法指向本地对象。将“First和”Last存储为引用字符串是否更可取 字符串引用存储器 此记录存储对字符串的引用。第一个和最后一个应该指向一个字符串。名称应该能够与我认为的相同,但这将导致非本地指针无法指向本地对象,而本地字符串被分配给该对象。因此,当前的变通解决方案是使用First和Last 类型段为记录 第一:积极的; 最后:肯定; 长度:自然长度:=0; 名称:访问字符串

有多种方法可以存储字符串引用,那么在示例代码中您将如何进行存储呢?当前的问题是存储对字符串的访问,因为它导致
非本地指针无法指向本地对象。将
“First
”Last
存储为引用字符串是否更可取

字符串引用存储器 此记录存储对字符串的引用。第一个
和最后一个应该指向一个字符串。
名称
应该能够与我认为的相同,但这将导致
非本地指针无法指向本地对象
,而本地字符串被分配给该对象。因此,当前的变通解决方案是使用
First
Last

类型段为记录
第一:积极的;
最后:肯定;
长度:自然长度:=0;
名称:访问字符串;
结束记录;
分配子字符串引用 注释行导致非本地指针不能指向本地对象。这是因为
是本地的<代码>源代码不是本地的,这是我希望子字符串引用的字符串

procedure Find(源:别名字符串;分隔符:字符;最后一个:out Natural;项数组:out段数组)为
P:正:=源的第一个;
开始
对于项_数组的范围循环中的I
声明
项:别名字符串:=分隔的字符串\u下一个(源,分隔符,P);
开始
当项目长度=0时退出;
Item_数组(I).长度:=Item'Length;
Item_数组(I).First:=Item'First;
Item_数组(I).Last:=Item'Last;
--Item_数组(I).名称:=Item'Access;
最后:=I;
结束;
端环;
结束;
例子
带有Ada.Text\u IO;
使用Ada.Integer\u Text\u IO;
主要程序是
使用Ada.Text\u IO;
使用Ada.Integer\u Text\u IO;
函数分隔\u字符串\u下一步(源:字符串;分隔符:字符;P:输入输出正)返回字符串为
A:正:=P;
B:阳性;
开始

当出现错误时,错误消息会准确地告诉您错误所在:
是本地声明的字符串,即在堆栈上,并且您正在将其地址分配给访问类型(指针)。我希望我不需要解释为什么那样不行

最直接的答案是在存储池或堆中为新字符串分配空间,这一点没有错,但也不是最佳做法,这是通过
new
完成的

Item : access String := new String'(Separated_String_Next (Source, Separator, P));
...
Item_Array (I).Name := Item;
请注意,其他一些记录成员,至少,
Length
似乎都是完全冗余的,因为它只是其同名属性的副本,所以可能应该被删除(除非有一部分图片我看不到)

有更好的答案。有时,您需要使用访问类型,并处理它们的对象生命周期以及它们可能出错的所有方式。但更常见的情况是,它们的外观暗示设计中的某些方面可以改进:例如:

  • 无界_字符串
    可以更简单地管理字符串
  • 您可以将长度用作
    记录上的判别符,并将实际字符串(不是访问)存储在记录本身中
  • Ada.Containers
    是一个标准的容器库,用于自己对存储进行抽象处理(就像在C++中使用STL一样)
  • 如果您确实决定需要访问类型,最好使用命名的访问类型
    type Str\u access is access String
    -然后您可以创建特定于
    Str_Acc
    类型的存储池,并在一次操作中释放整个池,以简化对象生命周期管理并消除内存泄漏
请注意,上面的内容本质上是源字符串的切片的“深度复制”。如果特别需要“浅层复制”它(即,引用适当的特定子字符串),并且您可以保证它的对象生存期,那么这个答案不是您想要的。如果是,请澄清问题的意图


对于“浅拷贝”,问题中的方法基本上失败了,因为
Item
已经是深拷贝了。。。在堆栈上

我能看到的最接近的方法是使源字符串具有别名。。。您必须按照您希望每个片段引用它的方式操作。。。并将其访问权限传递给Find过程

然后,每个段成为第一个、最后一个(冗余长度)和访问整个字符串(而不是子字符串)的元组

提取字符串的助手可能会很有用:

function get(S : Segment) return String is
begin
   return S.Name(S.First .. S.Last);
end get;
...
Put (get(Item_Array (I));
对于这种设计,我能看到的唯一理由是,要解析或剖析的字符串集几乎无法放入内存中,因此必须避免重复。也可能是嵌入式编程或类似的规程,其中不鼓励动态(堆)分配,甚至是非法的

我看不到在字符串中包含地址算法的解决方案,因为数组不仅仅是它的内容——如果指向其中,就会丢失属性。您可以对等效的C设计提出同样的批评:您可以用指针标识子字符串的开头,但您不能在不破坏原始字符串的情况下在子字符串的末尾粘贴空终止符


从大局来看。。。你需要什么,而不是如何实现它的低级细节,可能有更好的解决方案。

我的意思是做浅层复制。我不知道正确的术语是否叫做浅拷贝或引用。但这个答案可能会帮助其他人。
function get(S : Segment) return String is
begin
   return S.Name(S.First .. S.Last);
end get;
...
Put (get(Item_Array (I));