何时会重载 operator new 运算符?

9

可能重复:
有没有理由重载全局new和delete?

在什么情况下重载operator new是完全合理的?

我听说你可以在一个非常经常使用new的类中这样做。你能举个例子吗?

还有其他情况下,您是否想要重载operator new

更新:感谢到目前为止所有的答案。有人能给出一个简短的代码示例吗?这就是我上面提到的。像这样:这是一个小玩具类,这是该类的一个可工作的operator new


7
不是想表现得很高傲,但有用的答案可以通过搜索找到:https://dev59.com/N3M_5IYBdhLWcg3w9oQA - Skurmedel
@Skurmedel:但那个只是关于全局操作符new(和delete)的。我问的是一般情况下重载operator new,例如在一个类中。 - Frank
我不明白为什么原因会有任何不同,除了不同的范围之外。 - Skurmedel
1
请问能否重新打开这个问题,因为它的重点与被列为重复的那个问题不同:这个问题实际上是关于为什么要在类中添加这样一个运算符以及它会是什么样子的。 - Frank
1
我没有投票关闭,我无法这样做。也许您可以使用旗帜按钮吸引管理员的注意。 - Skurmedel
4个回答

12

每个类进行重载的一些原因:
1. 仪器化,例如跟踪分配,在调用者身上进行审计,如文件、行、堆栈。
2. 优化的分配例程, 例如内存池、固定块分配器。
3. 专业分配器,例如连续分配器,用于“启动时只分配一次”的对象——在游戏编程中经常用于需要持续整个游戏的内存等。
4. 对齐。这对大多数非桌面系统特别重要,尤其是在游戏控制台上,您经常需要以16字节边界进行分配。
5. 专门的内存存储器(同样适用于大多数非桌面系统),例如不可缓存内存或非本地内存。


4
我发现最好的方法是通过提供多个固定大小块的堆来防止堆碎片化。例如,你可以创建一个完全由4字节块组成的堆,另一个由8字节块等等。

这比默认的“全合一”堆更有效,因为你可以重复使用一个块,知道你的分配将适合第一个空闲块,而无需检查或遍历堆以寻找正确大小的可用空间。

缺点是你会占用更多内存,如果你有一个4字节堆和一个8字节堆,并且想要分配6字节...你必须将它放在8字节堆中,浪费2个字节。现在,这几乎不是问题(特别是当考虑到替代方案的开销时)。

如果你需要进行大量的分配,你可以优化此过程,并创建一个确切大小的堆。个人认为浪费一些字节并不是问题(例如,你正在分配大量的7字节,在8字节堆中使用并不是什么大问题)。

我们为一个高性能系统做到了这一点,效果非常好,大大减少了由于分配和堆碎片化引起的性能问题,并且对其余代码完全透明。

1
不确定您在哪个操作系统上尝试了这个。但是Windows堆管理器已经使用了这种方法。如果其他操作系统没有这样做,我会感到惊讶的。 - Hans Passant
1
C++内存管理针对快速出现和消失的小块进行了优化。尝试重新优化它可能不适用于普通程序员。此外,您提供的描述是几乎所有内存管理系统都使用的常见方案。重新实现它将不会带来任何好处。 - Martin York
一般来说,小块分配优化的工作范围是多大?我特别关注最近版本的GCC。 - Emile Cormier
在ptmalloc -> malloc.c中找到了我的答案(适用于Linux)。它说:“对于小的(默认情况下<= 64字节)请求,它是一个缓存分配器,维护快速回收块的池。” - Emile Cormier

3

为什么要重载operator new?

  1. 跟踪和分析内存,以检测内存泄漏
  2. 创建对象池(例如粒子系统)以优化内存使用

0

如果你想控制某个对象的内存分配,就可以采用这种方式。例如,当你有一些只会在堆上分配的小对象时,你可以为1k个对象分配空间,并先使用new运算符来分配1k个对象,然后一直使用该空间直到用完。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接