C++ 为什么我要禁止在堆中分配?

C++ 为什么我要禁止在堆中分配?,c++,class,stack,memory-management,heap,C++,Class,Stack,Memory Management,Heap,我最近读了很多关于“防止类的堆分配”(请参阅) 我能理解“怎么做”,但现在我不明白“为什么”有人会这么做 我想这一定有合理的原因,但我就是想不出来 简而言之:“为什么我可以禁止用户在堆中创建我的类的对象?”主要是因为堆栈分配的对象在超出范围时会自动清除,从而消除一大类错误,即内存分配错误。只有在堆栈上实例化对象时,某些类才有意义。例如,Boost或。通常,防止类的意外使用是一个好主意。例如,考虑依赖RAII技术的守护类。它们必须在堆栈上分配,并且在超出范围时执行其工作。没有人希望用户在堆中分配保

我最近读了很多关于“防止类的堆分配”(请参阅)

我能理解“怎么做”,但现在我不明白“为什么”有人会这么做

我想这一定有合理的原因,但我就是想不出来


简而言之:“为什么我可以禁止用户在堆中创建我的类的对象?”

主要是因为堆栈分配的对象在超出范围时会自动清除,从而消除一大类错误,即内存分配错误。

只有在堆栈上实例化对象时,某些类才有意义。例如,Boost或。

通常,防止类的意外使用是一个好主意。例如,考虑依赖RAII技术的守护类。它们必须在堆栈上分配,并且在超出范围时执行其工作。没有人希望用户在堆中分配保护对象,因此明确禁止这样做


显性比隐性好。Herb Shutter说,不正确地使用类(在堆中分配)和正确地使用类(在堆栈上)都很困难。

堆栈分配更快(无需搜索空间)对于某些类别的非常小的对象——考虑几何引擎中的3D点——在堆上单独分配这些点是创建悬空指针和引入大量开销的秘诀,然而,在很多计算中,它们是非常必要的。 因此,一种常见的机制是在实际包含3D点集合的对象中使用flyweight模式,如某些几何图元的描述,并允许在堆上使用它们作为计算的中间结果

现在,也就是说,需要特别注意避免在flyweight实现之间不必要地复制数据,例如ListOf3DPoints和用于中间结果的堆分配的3D点


一般来说,我发现有很多情况下,我将flyweight模式与堆分配功能结合起来,以实现最佳结果-flyweight提供持久存储,堆分配让我可以执行项目级操作,而无需生成另一个flyweight

我似乎会逆势而行(因此,我确实预计会有反对票,但请留下评论说明原因)

我不认为有任何理由禁止堆分配,主要是因为我不喜欢猜测我创建的类的潜在用途

作为一项设计规则,我倾向于对我的类的使用施加尽可能少的限制。这意味着尽可能少的假设。没有什么比仅仅因为它被禁止而不能做你想做的事情更令人恼火的了……原因可能是未知的,也可能是完全错误的(指图书馆作者的迷信/错误信仰)

<> P.>实用主义也教导说,实际上不可能真正阻止C++中的任何东西。例如,有些人已经谈到了守护者> >如果我想创建一个超级类(方便地添加日志),那么我将把守护类作为属性,甚至它的(原始类)。
new
操作符是私有的,我的超类可以在堆上实例化,除非它以某种方式复制该机制


所以,对我来说,这不是为什么或如何的问题。我只是不去摆弄库代码中的内存分配方案,而是由用户使用对她来说最方便的方法。

我真的想不出一个好的理由来解释你所指的问题。按照这个问题的当前措辞,你很可能会得到很多关于为什么的答案我更喜欢在堆栈中分配而不是在堆中分配吗?这与我为什么要禁止用户在堆中创建我的类的对象不同?@David:根据您的建议修改了措辞。谢谢。我修改了标题以反映实际问题。堆分配基本上有两种:直接和间接。An对象是间接堆分配的,如果它是子对象(基或成员)另一个被堆分配的对象。问题目前没有区分它们,答案也没有解决。但是提到的潜在原因可能适用于或可能不适用于间接堆分配的对象。通常,如果这样做总是错误的,您只希望显式禁止(例如,浅层复制对象以释放其析构函数中的资源),这不仅仅是因为你想不出允许它的理由。动态分配可能是一个错误有什么原因吗?为了节省大约一百条CPU指令而引入语义梦魇对我来说听起来像是过早优化的案例。@Visage:堆分配的开销远远超过一百条CPU指令-最重要的是如果过度使用,间接指向堆的成本可能会很高,此外,管理内存会使用额外的周期和内存。基本事实是,从性能角度看,堆栈分配更好,语义也更清晰。@Visage:也许您可以提供一个示例,其中堆栈和堆都可以同时使用d堆分配比堆栈分配更干净…我不认为只有一个例子。现在,考虑一下:
void foo(){for(int*I=new int(0);*I<10<++*I{…}
--哎哟,如何在那里释放指针?在堆栈中使用智能指针--:
void foo(){for(auto_ptr I(new int(0));*I<10;++*I){…}
…我们仍然在使用堆栈,而代码更复杂,或者不是吗?我不确定在现实生活中永远不会使用的人为示例是否真的支持了您的论点。@Visage:问题是堆栈分配总是比代码中的堆分配简单。我提供了第一个示例:lo的控制变量使用纯堆分配无法写入op。N