为什么要替换默认的new和delete运算符?

时间:2011-08-22 15:04:02

标签: c++ operator-overloading new-operator c++-faq delete-operator

为什么 会用自定义newdelete运算符替换默认运算符newdelete

在非常有启发性的C ++ FAQ中,这是Overloading new and delete的延续:
Operator overloading.

此常见问题解答的后续条目是:
How should I write ISO C++ standard conformant custom new and delete operators?

<子> 注意:答案是基于Scott Meyers的“更有效的C ++”的经验教训 (注意:这是Stack Overflow's C++ FAQ的一个条目。如果您想批评在此表单中提供常见问题解答的想法,那么the posting on meta that started all this就是这样做的地方。在C++ chatroom中监控了这个问题,首先是FAQ的想法,所以你的答案很可能会被那些提出想法的人阅读。)

7 个答案:

答案 0 :(得分:66)

答案 1 :(得分:12)

答案 2 :(得分:6)

  

许多计算机体系结构要求将特定类型的数据放在特定类型地址的内存中。例如,体系结构可能要求指针出现在四倍的地址处(即,四字节对齐),或者双倍必须出现在八倍的地址处(即,八字节对齐)。不遵守此类约束可能会导致运行时出现硬件异常。其他架构更宽容,并且可能允许它在降低性能的情况下工作。

澄清一下:如果架构需要,例如double数据是八字节对齐的,那么就没有什么可以优化的了。任何类型的适当大小的动态分配(例如malloc(size)operator new(size)operator new[](size)new char[size] size >= sizeof(double))都可以保证正确对齐。如果实现没有做出这种保证,那就不符合要求。在这种情况下,改变operator new做'正确的事'将是“修复”实施,而不是优化。

另一方面,某些体系结构允许对一种或多种数据类型进行不同(或所有)类型的对齐,但根据这些相同类型的对齐提供不同的性能保证。然后,实现可以返回存储器(再次,假设具有适当大小的请求),该存储器被次优地对齐,并且仍然是符合的。这就是这个例子。

答案 3 :(得分:4)

  

带有一些编译器的运算符new不保证动态分配双精度的八字节对齐。

请引用。通常,默认的new运算符只比malloc包装器稍微复杂一些,按标准,它返回的内存适合于目标体系结构支持的 ANY 数据类型。

并不是说我没有充分的理由为自己的班级重载新的和删除...而你在这里已经触及了几个合法的,但上面不是其中之一。

答案 4 :(得分:3)

与使用情况统计相关:按子系统预算。例如,在基于控制台的游戏中,您可能希望为3D模型几何保留一些内存,一些用于纹理,一些用于声音,一些用于游戏脚本等。自定义分配器可以按子系统标记每个分配并发出在超出个人预算时发出警告。

答案 5 :(得分:3)

我用它在特定的共享内存领域分配对象。 (这与@Russell Borogove提到的类似。)

多年前,我为CAVE开发了软件。这是一个多墙VR系统。它用一台电脑驱动每台投影机; 6是最大值(4个墙壁,地板和天花板),而3个更常见(2个墙壁和地板)。这些机器通过特殊的共享内存硬件进行通信。

为了支持它,我从我的普通(非CAVE)场景类派生出来,使用一个新的“new”,它将场景信息直接放在共享内存领域。然后我将指针传递给不同机器上的从属渲染器。

答案 6 :(得分:3)

似乎值得重复my answer from "Any reason to overload global new and delete?"此处的列表 - 请参阅答案(或确实other answers to that question)以获取更详细的讨论,参考和其他原因。这些原因通常适用于本地运算符重载以及默认/全局重载,以及C malloc / calloc / realloc / free重载或挂钩。

  

我们重载全局new和delete运算符,我为很多人工作   原因:

     
      
  • 汇集所有小额分配 - 降低开销,减少碎片,可以提高小型重型应用的性能
  •   
  • 框架具有已知生命周期的分配 - 忽略所有释放,直到此期间结束,然后释放所有这些   在一起(诚然,我们通过本地运营商超载来做到这一点   比全球)
  •   
  • 对齐调整 - 到缓存行边界等
  •   
  • 分配填充 - 帮助公开未初始化变量的使用
  •   
  • 免费填充 - 帮助公开以前删除的内存的使用情况
  •   
  • 延迟免费 - 提高免费填充的效果,偶尔提高性能
  •   
  • 哨兵 fenceposts - 帮助公开缓冲区溢出,欠载和偶尔的狂野指针
  •   
  • 重定向分配 - 考虑NUMA,特殊内存区域,甚至将单独的系统分开存储在内存中(例如   嵌入式脚本语言或DSL)
  •   
  • 垃圾收集或清理 - 对嵌入式脚本语言再次有用
  •   
  • 堆验证 - 每N次分配/释放可以遍历堆数据结构,以确保一切正常
  •   
  • 会计,包括泄漏跟踪使用情况快照/统计信息(堆栈,分配年龄等)
  •