Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 对象创建:指向值类型对象内动态分配的数据的指针-好还是坏?_C - Fatal编程技术网

C 对象创建:指向值类型对象内动态分配的数据的指针-好还是坏?

C 对象创建:指向值类型对象内动态分配的数据的指针-好还是坏?,c,C,我有一个简单的结构: typedef struct { int width, height; unsigned char *pixels; } image; 哪一个是更好的API image *imagecreate(int w, int h) { image *img = malloc(sizeof(image)); img->width = w; img->height = h; img->pixels = calloc(w

我有一个简单的结构:

typedef struct {
    int width, height;
    unsigned char *pixels;
} image;
哪一个是更好的API

image *imagecreate(int w, int h) {
    image *img = malloc(sizeof(image));
    img->width = w;
    img->height = h;
    img->pixels = calloc(w * h, 3);
    return img;
}

void imagefree(image *img) {
    free(img->pixels);
    free(img);
}

?


对于这样一个小的结构,它只是一个指向实际动态分配数据的指针的包装器,对它执行额外的malloc()似乎有些过分。但另一方面,(对我来说)将指向动态分配内存的指针隐藏在值类型中感觉很不自然。有人可能认为您不必释放它。

不同之处在于,您的
结构在第一种情况下是动态分配的,在第二种情况下是自动分配的。这是个人偏好、编码标准和观点的问题。第二种方法对我来说似乎更安全,因为它少了一种
免费
记得要做的事,但既然你必须
免费
,那就没那么重要了


注意,在第二种情况下,
struct
被复制到返回值中。你似乎很好地处理了其中的指针,但这是一个潜在的地雷。

我同意第一个。假设您的结构中有一个描述符“char name[100]”,那么第二个将使用100字节的堆栈空间,这必须由操作系统处理,而第一个内存将由您自己处理(使用自写垃圾收集器而不是标准的malloc)您可以随意移动对象的句柄,而无需考虑有限的堆栈空间。

您正在谈论的是API。因此,您的客户应该能够轻松正确地使用它,而不可能错误地使用它,这一点至关重要

选项2的小改进#

例如,如果我是第二个API的用户:

image imagecreate(int w, int h);
void imagefree(image *img);
我可能甚至不会注意到需要调用
imagefree
,因为
imagecreate
返回一个对象,而不是指向对象的指针,而
imagefree
需要一个指针。我可能认为
imagefree
只是堆分配对象的
delete image
包装。所以我不会将其用于“堆栈”对象

因此,这是更好的:

image imagecreate(int w, int h);
void imagefree(image img);
虽然在
image
中有一个堆分配的成员,但将其隐藏在这些API中是很好的。而且他们有一致的“外观”,这更好,更不容易出错

那么选项1呢?

至于你的第一个选择,是不是更好?这取决于(个人)。就我而言,我倾向于选择1

为什么?


虽然我们没有办法在C++中用RAII这样的析构函数来实现资源自动销毁,但是通常看到C程序员看到的是从API返回的指针(我们对指针敏感,不是吗?)。他们很可能一直在问自己:它是在
imagecreate
中动态分配的吗?我需要通过其他API释放它吗?

我当然更喜欢第一个,我认为指针更容易管理。我通常将字符串作为char*进行管理。但你是对的,如果我的结构在未来增长,我会浪费更多的堆栈空间。你说服了我。我可能会使用指针返回值版本。
image imagecreate(int w, int h);
void imagefree(image img);
image *imagecreate(int w, int h);
void imagefree(image *img);