我最近投身于图形编程,我注意到许 multimap 形引擎(即 Ogre)和总体上的许多编码人员更喜欢动态初始化类实例。这是来自 Ogre Basic Tutorial 1 的示例
//...
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");
//...
ogreHead
和 headNode
数据成员和方法被称为 ogreHead->blabla
。
为什么要乱用对象指针而不是普通对象?
顺便说一句,我还在某处读到堆内存分配比堆栈内存分配慢得多。
最佳答案
堆分配不可避免地比栈分配慢得多。更多关于“慢多少?”之后。但是,在许多情况下,选择是“为您做出的”,原因如下:
- 堆栈有限。如果你用完了,应用程序几乎总是会被终止——没有真正好的恢复,甚至打印一条错误消息说“我用完了堆栈”可能很难......
- 当您离开进行分配的函数时,堆栈分配“消失”。
- 可变性的定义更加明确且易于处理。 C++ 不能很好地处理“可变长度数组”,当然也不能保证在所有编译器中都能正常工作。
堆比堆栈慢多少?
我们稍后会谈到“这很重要”。
对于给定的分配,堆栈分配只是一个减法操作 [1],其中至少 new
或 malloc
将是一个函数调用,甚至可能最简单的分配器将是几十条指令,在复杂的情况下是数千条[因为必须从操作系统获取内存,并清除它以前的内容]。所以从 10 倍到“无限”慢的任何东西,给予或接受。确切的数字将取决于代码运行的确切系统、分配的大小,以及通常“对分配器的先前调用”(例如,一长串“释放”分配会使分配新对象变慢,因为一个很好的匹配必须搜索)。当然,除非你采用堆管理的“鸵鸟”方法,否则你还需要释放对象并应对“内存不足”,这会增加代码执行和代码复杂性的代码/时间。
然而,通过一些相当聪明的编程,这在很大程度上可以被隐藏——例如,分配一些在对象的生命周期内长期保持分配状态的东西,将“无需担心”。在 3D 游戏中为每个像素或每个三角形从堆中分配对象显然不是一个好主意。但是如果对象的生命周期是很多帧甚至是整个游戏,那么分配和释放它的时间几乎为零。
同样,不是进行 10000 个单独的对象分配,而是为 10000 个对象分配一个。对象池就是这样一个概念。
此外,分配时间通常不是花费时间的地方。例如,从磁盘的文件中读取三角形列表比为同一三角形列表分配空间要花费更长的时间——即使你分配了每个三角形列表!
对我来说,规则是:
- 它是否适合堆栈?通常几千字节就可以了,很多千字节不太好,而兆字节肯定不行。
- 是否已知数量(例如对象数组),以及可以将其放入堆栈的最大值?
- 你知道对象是什么吗?换句话说,抽象/多态类可能需要在堆上分配。
- 它的生命周期是否与它所在的范围相同?如果不是,则使用堆(或进一步向下堆叠,并将其向上传递)。
[1] 如果堆栈“向高地址增长”,或者添加 - 我不知道有这样的架构的机器,但它是可以想象的,我认为已经制造了一些。 C 当然不 promise 堆栈的增长方式,或者关于运行时堆栈如何工作的任何其他内容。
关于c++ - 更喜欢堆而不是堆栈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28385280/