1.8 另一种实现 - 包
不需要改变 Set.h
中的接口,我们来改变接口的实现方式。这次使用动态内存分配,使用结构体来表示集合和对象:
struct Set{
unsigned count;
};
struct Object{
unsigned count;
struct Set* in;
};
count
用于跟踪集合中的元素的计数个数。对于一个元素来说, count
记录这个元素被集合添加的次数。如果我们想递减 count
值,可调用 drop()
方法。一旦一个元素的 count
值为 0
,我们就可以删除它,我们拥有一个包,即,一个集合,集合中的元素拥有一个对 count
的引用。
因为我们使用动态内存分配机制去表示集合集和对象集,所以需要初始化 Set
和 Object
描述符,以便于 new()
能够知道需要分配多少内存:
static const size_t _Set=sizeof(struct Set);
static const size_t _Object=sizeof(struct Object);
const void * Set=&_Set;
const void * Object=&_Object;
new()
方法现在更加简单:
void * new (const void * type,...)
{
const size_t size= *(const size_t*)type;
void* p=calloc(1,size);
assert(p);
return p;
}
delete()
可直接把参数传递给 free()
- 标准化 C 语言中 一个空的指针可以传进 free()
。如下:(如意调用)
void delete (void * _item)
{
free(_item);
}
add()
方法多多少少对它的指针自变量比较信任。它会增加元素的引用计数和集合的引用计数。
void* add(void* _set,const void* _element)
{
struct Set *set=_set;
struct Object* element=(void*)_element;
assert(set);
assert(element);
if(!element->in){
element->in=set;
}
else{
assert(element->in==set);
}
++element->count;
++set->count;
return element;
}
find()
方法仍然会检查,一个元素是否指向一个适当的集合:
void* find(const void* _set,const void * _element)
{
const struct Object* element=_element;
assert(element);
return element->in==_set?(void*)element:0;
}
contains()
方法基于 find()
方法来实现,仍然保持不变。
若 drop()
在集合中找到它要操作的元素,它将递减元素的引用计数和元素在集合中的计数。如果引用计数减为 0,这个元素即被从集合中删除:
void* drop(void * _set,const void * _element)
{
struct Set* set=_set;
struct Object* element=find(set,_element);
if(element){
if(--element->count==0){
element->in=0;
}
--set->count;
}
return element;
}
现在我们可以提供一个新的方法,用来获取集合中的元素个数:
unsigned count(const void* _set)
{
const struct Set* set=_set;
assert(set);
return set->count;
}
当然啦,直接让程序通过读 对象 .count
显得比较简单,但是我会坚持不去披露集这样的实现。与应用程序重写临界值的危险性相比上述功能的调用的开销是可忽视的。
包的表现与集合是不同的。一个元素可被添加多次;当一个元素的删除次数等于其被添加的次数时,这个元素被从集合中删除, contains()
方法仍然能够找着它。测试程序的运行结果如下:
ok
drop?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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