文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
2.6 另一种实现 - 原子
为了列举我们通过构造器和析构器到底能够做什么,我们实现了原子,所谓原子就是一个唯一的字符窜对象;如果两个原子包含相同的字符窜,则他们是相等的。原子是很容易比较的:如果两个参数的指针不同,则 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论