【发布时间】:2019-05-10 15:45:19
【问题描述】:
我目前正在解决的设计问题是迭代某个内存区域,并在每次这样的迭代中从该内存中检索客户感兴趣的一些元数据。我目前看到 2 个解决方案:
我。
struct queue;
struct queue_element_view{
int id;
char *description;
};
//0 - if ok, -1 - if end of queue reached
int next(struct queue*);
//0 - if ok, -1 - if end of queue reached
int current_element_view(struct queue*, struct queue_element_view *);
因此,队列不透明结构可以通过next 函数进行遍历,并且由于队列元素是平台相关的,并且我想保持库跨平台,因此我提供了一个独立于平台的struct queue_element_view,它在所有平台上都是合理的。
缺点:
如果客户端这样写代码:
struct queue *queue_ptr = //
struct queue_element_view current_out;
current_element_view(queue_ptr, ¤t_out);
//current_out now contains current's element meta data
next(queue_ptr);
//current_out now may contain unspecified data
//since queue's current element changed.
所以在调用current_element_view 之后再调用next 会破坏current_out。
二。
struct queue;
struct queue_element_view;
struct queue_element_view *allocate_view(void);
int * get_id(struct queue_element_view *);
char * get_description(struct queue_element_view *);
//0 - if ok, -1 - if end of queue reached
int next(struct queue*);
//0 - if ok, -1 - if end of queue reached
int current_element_view(struct queue*, struct queue_element_view *);
在这种情况下,我们分配了struct queue_element_view 和current_element_view 将数据复制到结构queue_element_view * 指向的对象,因此next 不会破坏数据。
缺点:
它涉及一个函数附加调用来简单地检索
int和char *字段这使得测试公共 api 变得更加复杂。
所以我有点困惑哪一个更可取/可读?或许还有其他选择?
【问题讨论】:
-
你能解释一下这个问题吗?数据会损坏吗?还是只是过时了?
-
@AvivGoll 大部分已经过时,但如果调用
next后的实现回收(尚未)前一个元素的内存,它将包含悬空指针。我倾向于在从客户端遍历的过程中隐藏内存回收细节 -
@St.Antario,如果您的想法是
next()将回收先前由current_element_view()分配的内存,那么这确实应该成为问题的一部分。我认为这比目前在该替代方案的描述中提出的任何问题都更具潜在问题。 -
@JohnBollinger 以下是合理的选择吗?我让
struct queue_element_view不透明并添加函数const struct queue_element_view * current_element_view_pointer(struct queue *);。它返回的指针始终包含当前元素的相关数据,客户端不可修改,但在调用next时保持一致? -
id不能悬空。您可以复制描述并为视图添加免费方法。关于过时的问题,第二个解决方案是如何解决的?
标签: c api-design software-design opaque-pointers