gpt4 book ai didi

在 C 中创建 "classes",在栈上还是在堆上?

转载 作者:太空狗 更新时间:2023-10-29 16:19:12 25 4
gpt4 key购买 nike

每当我看到 C“类”(任何旨在通过访问将指向它的指针作为第一个参数的函数使用的结构)时,我看到它们是这样实现的:

typedef struct
{
int member_a;
float member_b;
} CClass;

CClass* CClass_create();
void CClass_destroy(CClass *self);
void CClass_someFunction(CClass *self, ...);
...

在这种情况下,CClass_create 总是 malloc 它是内存并返回指向它的指针。

每当我看到 new 不必要地出现在 C++ 中时,这通常会让 C++ 程序员发疯,但这种做法在 C 中似乎是可以接受的。是什么原因造成的?堆分配的结构“类”如此普遍背后有什么原因吗?

最佳答案

这有几个原因。

  1. 使用“不透明”指针
  2. 缺少析构函数
  3. 嵌入式系统(栈溢出问题)
  4. 容器
  5. 惯性
  6. “懒惰”

让我们简要地讨论一下。

对于不透明指针,它使您能够执行如下操作:

struct CClass_;
typedef struct CClass_ CClass;
// the rest as in your example

因此,用户看不到 struct CClass_ 的定义,将她与对它的更改隔离开来,并启用其他有趣的东西,比如为不同的平台实现不同的类。

当然,这禁止使用CClass的堆栈变量。但是,OTOH,可以看到这并不禁止静态分配 CClass 对象(从某个池中) - 由 CClass_create 或可能是 CClass_create_static< 之类的另一个函数返回.

缺少析构函数 - 由于 C 编译器不会自动析构您的 CClass 堆栈对象,您需要自己动手(手动调用析构函数)。所以,剩下的唯一好处就是堆栈分配通常比堆分配快。 OTOH,你不必使用堆——你可以从池、竞技场或类似的东西分配,这可能几乎和堆栈分配一样快,没有下面讨论的堆栈分配的潜在问题。

嵌入式系统 - 您知道,堆栈不是“无限”资源。当然,对于当今“常规”操作系统(POSIX、Windows...)上的大多数应用程序来说,它几乎是。但是,在嵌入式系统上,堆栈可能低至几 KB。这是极端的,但即使是“大型”嵌入式系统也有以 MB 为单位的堆栈。因此,如果过度使用,它将用完。当它发生时,大多数情况下无法保证会发生什么 - AFAIK,在 C 和 C++ 中都是“未定义的行为”。 OTOH,CClass_create() 可以在内存不足时返回 NULL 指针,您可以处理它。

容器 - C++ 用户喜欢堆栈分配,但是,如果您在堆栈上创建一个 std::vector,它的内容将被分配到堆上。当然,你可以调整它,但这是默认行为,它让人们更容易说“容器的所有成员都是堆分配的”,而不是试图弄清楚如果它们不是堆分配的如何处理。

Inertia - 好吧,OO 来自 SmallTalk。那里的一切都是动态的,因此,对 C 的“自然”翻译是“将一切都放在堆上”的方式。所以,第一个例子就是这样,他们激励了其他人很多年。

惰性”——如果你知道你只想要堆栈对象,你需要像这样的东西:

CClass CClass_make();
void CClass_deinit(CClass *me);

但是,如果你想同时允许堆栈和堆,你需要添加:

CClass *CClass_create();
void CClass_destroy(CClass *me);

这对实现者来说需要做更多的工作,但也会让用户感到困惑。一个人可以制作略有不同的界面,但这不会改变您需要两套功能的事实。

当然,“容器”的原因也部分是“懒惰”的原因。

关于在 C 中创建 "classes",在栈上还是在堆上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31673065/

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