gpt4 book ai didi

c - 就地与分配 API

转载 作者:行者123 更新时间:2023-12-01 23:42:03 25 4
gpt4 key购买 nike

我需要在 C 中创建一个库,我想知道如何管理对象:返回分配的(例如:fopen、opendir)或就地初始化(例如:GNU hcreate_r)。

据我了解主要是a question of taste ,我倾向于选择分配 API,因为在进行惰性初始化(通过测试对象指针是否为 NULL)时方便。

然而看完Ulrich's paper (PDF) ,我想知道这种设计是否会导致引用问题的局部性,特别是如果我从其他人那里组合对象:

struct opaque_composite {
struct objectx *member1;
struct objecty *member2;
struct objectz *member2;
/* ... */
};

这样一个对象的分配将产生其他子分配的级联。这在实践中有问题吗?还有其他我应该注意的问题吗?

最佳答案

要考虑的是函数构造的对象类型是否不透明。不透明类型仅在头文件中前向声明,您唯一能用它做的就是拥有一个指向它的指针并将该指针传递给单独编译的 API 函数。标准库中的FILE就是这样一个不透明的类型。对于不透明类型,您别无选择,只能提供分配和释放函数,因为用户没有其他方法来获取对该类型对象的引用。

如果类型不是不透明的——也就是说,struct的定义在头文件中——拥有一个只做初始化的函数会更通用——如果需要的话,另一个进行终结——但没有分配和解除分配。原因是通过这个接口(interface),用户可以决定是否将对象放入堆栈......

struct widget w;
widget_init(&w, 42, "lorem ipsum");
// use widget…
widget_fini(&w);

...或者在堆上。

struct widget * wp = malloc(sizeof(struct widget));
if (wp == NULL)
exit(1); // or do whatever
widget_init(wp, 42, "lorem ipsum");
// use widget…
widget_fini(wp);
free(wp);

如果您认为输入太多,您或您的用户自己可以轻松地提供便利功能。

inline struct widget *
new_widget(const int n, const char *const s)
{
struct widget wp = malloc(sizeof(struct widget));
if (wp != NULL)
widget_init(wp, n, s);
return wp;
}

inline void
del_widget(struct widget * wp)
{
widget_fini(wp);
free(wp);
}

反过来是不可能的。

接口(interface)应始终提供组成更高级别抽象的基本构建 block ,但不应因过度限制而使合法使用成为不可能。

当然,这给我们留下了一个问题,即何时使类型不透明。一个好的经验法则——我第一次在 Linux 内核的coding standards中看到的——可能是只有当没有你的用户可以有意义地访问的数据成员时才使类型不透明。我认为这条规则应该稍微改进一下,以考虑到非不透明类型允许“成员”函数在头文件中作为inline版本提供,从性能的角度来看这可能是可取的。另一方面,不透明类型提供了更好的封装(特别是因为 C 无法限制对struct的成员的访问)。如果使它不透明会迫使我将#include header 放入我的库的头文件中,我也会更容易地倾向于不透明类型,因为它们提供了在我的类型中用作成员的类型的定义。 (对于#include<stdint.h>uint32_t我没意见。对于#include<unistd.h>这样的大标题,我不太容易,我当然会尽量避免必须#include ”来自第三方库的 header ,例如<curses.h>。)

关于c - 就地与分配 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35451547/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com