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