在Ada中这很简单:
输入ITEM_RECORD;类型ITEM_ACCESS是访问ITEM_RECORD;输入ITEM_RECORD是记录 ITEM:item_type; 下一个:item_access; Pred:item_access;结束记录;简单, …
为了使用智能指针,你的智能指针 必须 使用不完整的类型。因此,您还需要提供一个删除访问变量(当然还有访问类型)的终结过程。这当然也意味着您的分配函数需要采用访问类型而不是变量。最后,你绝对是 需要 使用弱指针来打破引用计数智能指针生成的循环引用。
generic type Item_Type(<>); type Item_Access is access Item_Type; with procedure Finalize(Ref : in out Item_Access); package Pointers is function Make(Ref : not null Item_Access) return Smart_Pointer; -- other stuff end Pointers;
然后你可以这样做:
type Node_Impl; type Node_Access is access Node_Impl; procedure Finalize(Ref : in out Node_Access); package Ptrs is new Pointers(Node_Impl,Node_Access,Finalize); subtype Node is Ptrs.Smart_Pointer; subtype Weak_Node is Ptrs.Weak_Pointer; type Node_Impl is record Value : Some_Type; Next : Node; Prev : Weak_Node; end record;
这是我用来制作带有智能指针的AVL树的示例规范。我没有方便的链表示例。
package Trees is type Node; type Node_Access is access Node; procedure Finalize(Memory : in out Node_Access); package Node_Smart_Access is new Smart_Access (Item_Type => Node, Item_Access => Node_Access, Finalize => Finalize, Atomic_Increment => True); type Node is record Value : Integer := 0; Height : Integer := 1; Parent : Node_Smart_Access.Weak_Access; Left : Node_Smart_Access.Shared_Access; Right : Node_Smart_Access.Shared_Access; end record; type Tree is tagged record Root : Node_Smart_Access.Shared_Access; end record; end Trees;
我的智能指针规范是:
generic type Item_Type(<>); type Item_Access is access Item_Type; with procedure Finalize(Memory : in out Item_Access); Atomic_Increment : Boolean := True; package Smart_Access is type Shared_Access is new Ada.Finalization.Controlled with private; type Weak_Access is new Ada.Finalization.Controlled with private; -- more stuff package Make is function Shared_Access (Source : in not null Item_Access) return Smart_Access.Shared_Access; -- more stuff end Make; private -- implementation end Smart_Access;
这很麻烦,但如果你想在Ada中使用智能指针制作自引用类型,则需要这样做。另请注意,如果在智能指针的规范中使用不完整类型,则某些版本的GNAT具有Implicit_Dereference方面的编译器错误。如果您使用的版本存在错误,它们将在编译时导致编译器崩溃。
由于循环依赖性,您无法创建要创建的结构。想一想:
通用包定义了一个指针。的结构和实施 Pointer_Type (可能)取决于通用参数 Item_Type (这不一定是真的,但如果不是,那就没有必要了 Item_Type 作为通用参数)。现在 Item_Type 在你的泛型包的实例化中包含来自泛型包的两个智能指针,因此,取决于它的结构 Pointer_Type 。这是一个经典的鸡蛋或鸡蛋问题。
Pointer_Type
Item_Type
所以解决方案是改变你的类型的设计。让我给你一些指示(没有双关语):
看起来你正在实现一个双向链表。请注意,由于列表的循环特性,使用实现引用计数的智能指针是一个严重的错误。如果你的列表至少包含两个项目,那么任何东西都不会被释放,因为它们总是指向对方。因此,除非您的智能指针正在进行循环检测(根据您的规格无法实现),否则您无法使用智能 以你想要的方式指针。
一个可能的解决方案是拥有智能指针 Item_Type 而不是记录。您需要手动取消分配记录,但无论如何,您需要执行此操作,如上所述。
另一种解决方案是为整个列表建立一个全局引用计数器。创建一个不透明的列表类型,为列表提供访问器和迭代器子例程,分发项目的智能指针。智能指针增加和减少整个列表上的引用计数,一旦对列表的最后一次引用消失,整个列表将被释放。因此,只要存在至少一个对其中某些内容的引用,该列表就存在。此解决方案需要您自己实现引用计数,因为它专门用于列表结构。
最后,你当然可以使用 Ada.Containers.Doubly_Linked_Lists 像杰弗里建议的那样。你可以把聪明的指针放到你的 Item_Type 在那里,正如我在第一个解决方案中建议的那样。
Ada.Containers.Doubly_Linked_Lists