返回介绍

2.6 另一种实现 - 原子

发布于 2025-02-24 22:44:36 字数 1895 浏览 0 评论 0 收藏 0

为了列举我们通过构造器和析构器到底能够做什么,我们实现了原子,所谓原子就是一个唯一的字符窜对象;如果两个原子包含相同的字符窜,则他们是相等的。原子是很容易比较的:如果两个参数的指针不同,则 differ() 返回真。原子的构造和销毁要付出一定的代价;我们为所有的原子维持了一个循环链表,并计数原子被克隆的次数,如下:

struct String {
     const void * class;        /* must be first */
     char * text;
     struct String * next;
     unsigned count;
};

static struct String * ring;    /* of all strings */

static void * String_clone (const void * _self)
{   struct String * self = (void *) _self;

     ++ self -> count;
     return self;
}

所有的原子的循环链表被 ring 所标记,通过它的成员 .next 来扩展,并使用构造器和析构器来维持。在构造器保存文本之前,首先会遍历链表是否有相同的文本已经存在,如下的代码插入到 String_ctor() 之前:

if (ring)
{  
struct String * p = ring;
     do{
        if (strcmp(p -> text, text) == 0)
        {  
++ p -> count;
           free(self);
           return p;
        }
     }while ((p = p -> next) != ring);
}
else{
     ring = self;
}
self -> next = ring -> next, ring -> next = self;
self -> count = 1;

如果我们找到了相同文本的原子,则增加它的引用计数 count 值,释放新的对象 self 返回当前找的的原子指针 p 。否则我们向循环链表中插入一个新字符串对象并设置其引用计数为 count 为 1。

析构器防止删除引用计数为非零的原子。如下的代码被插入到 String_dtor() 之前:

if (-- self -> count > 0){
     return 0;
}
assert(ring);
if (ring == self){
     ring = self -> next;
}
if (ring == self){
     ring = 0;
}
else{    
struct String * p = ring;
     while (p -> next != self){   
p = p -> next;
        assert(p != ring);
     }
     p -> next = self -> next;
}

如果对引用计数的减 1 操作计数扔为正数,则返回一个空指针,以便于 delete() 手下留情。否则如果我们的字符串对象是最后一个对象我们清除循环链表标记符,否则从链表中删除我们的字符串。

把上述的实现加入到 2.4 的程序中,注意,对一个字符串对象的克隆此时为源字符串对象本身,运行结果如下:

sizeOf(a)==16
ok
clone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文