我最近读了很多关于“防止类的堆分配”(见这个问题)。
我能够理解“如何”,但现在我无法弄清楚“为什么”有人愿意这样做。
我想这一定有正当的理由,但我就是想不通。
简而言之:“为什么我要禁止用户在堆中创建我的类的对象?”
我最近读了很多关于“防止类的堆分配”(见这个问题)。
我能够理解“如何”,但现在我无法弄清楚“为什么”有人愿意这样做。
我想这一定有正当的理由,但我就是想不通。
简而言之:“为什么我要禁止用户在堆中创建我的类的对象?”
某些类只有在对象在堆栈上实例化时才有意义。例如,Boost scoped_ptr或lock_guard。
主要是因为堆栈分配的对象在超出范围时会自动清理,从而消除了一大类错误——即内存分配错误。
我会逆流而上(所以我确实期待投票,但请发表评论以说明原因)。
我看不出有任何理由禁止堆分配,主要是因为我不喜欢猜测我创建的类的潜在用途。
作为设计规则,我倾向于尽可能少地限制类的使用。这意味着尽可能少的假设。没有什么比仅仅因为它被禁止而无法做你想做的事更令人抓狂的了……原因不明或完全错误(表示图书馆作者的迷信/错误信念)。
此外,实用主义教导说,实际上不可能在 C++ 中阻止任何事情。例如,有些人谈到了守卫——>如果我想创建一个超类(方便地添加日志记录)怎么办?然后我会将保护类作为属性,即使它的(原始类)new
运算符是私有的,我的超类也可以在堆上实例化,除非它以某种方式复制机制。
所以,对我来说,这不是为什么或如何的问题。我只是不摆弄库代码中的内存分配方案,由用户决定使用对她来说最方便的东西。
通常最好防止类的意外使用。例如,考虑依赖 RAII 技术的 Guard 类。它们必须在堆栈上分配,并且在它们超出范围时完成它们的工作。没有人期望用户在堆中分配保护对象,因此明确禁止。
显式优于隐式。Herb Shutter 说,错误地使用你的类(在堆中分配)一定很难,而且很容易正确使用(在堆栈上)。
堆栈分配更快(无需搜索空间)。
对于某些类别的非常小的对象 - 考虑几何引擎中的 3D 点 - 在堆上单独分配这些点是创建悬空指针并引入大量开销的秘诀 - 但是,它们在大量计算中至关重要
因此,一种常见的机制是在实际包含 3D 点集合的对象中使用享元模式,例如对某些几何实体的描述,并允许它们在堆上用作计算的中间结果。
现在,也就是说,需要特别注意避免在享元实现之间不必要的数据复制,例如 ListOf3DPoints 和堆分配的用于中间结果的 3D 点。
总的来说,我发现在很多情况下,我将享元模式与堆分配功能相结合以实现最佳结果 - 享元提供持久存储,堆分配让我无需生成另一个享元即可执行项目级别操作