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

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

为什么要替换默认运算符 newdelete带定制 newdelete运营商?
这是 Overloading new and delete 的延续在非常有启发性的 C++ 常见问题解答中:
Operator overloading.
此常见问题解答的后续条目是:
How should I write ISO C++ standard conformant custom new and delete operators?

注意:答案基于 Scott Meyers 的 More Effective C++ 的经验教训。
_(注意:这是 [Stack Overflow 的 C++ 常见问题解答](https://stackoverflow.com/questions/tagged/c++-faq)的入口。如果您想批评以这种形式提供常见问题解答的想法,那么[开始这一切的元数据发布](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag) 将是这样做的地方. 该问题的答案在 [C++ 聊天室](https://chat.stackoverflow.com/rooms/10/c-lounge) 中进行监控,FAQ 的想法最初是从这里开始的,因此您的答案很可能被提出这个想法的人阅读。)_

最佳答案

可以尝试更换newdelete运营商出于多种原因,即:

检测使用错误:

不正确使用 new 的方式有很多种。和 delete可能会导致可怕的未定义行为和内存泄漏。
各自的例子是:
使用多个 deletenew ed 内存 & 不调用 delete在使用 new 分配的内存上.
重载运算符 new可以保留已分配地址列表和重载运算符 delete可以从列表中删除地址,那么很容易检测到此类使用错误。

同样,各种编程错误都会导致数据超限 (写入超出分配块的末尾)和 欠载 (在分配的块开始之前写入)。
重载运算符 new可以过度分配块并在客户端可用的内存之前和之后放置已知的字节模式(“签名”)。重载的操作符删除可以检查签名是否仍然完整。
因此,通过检查这些签名是否不完整,可以确定在分配块的生命周期内的某个时间发生了溢出或欠载,并且操作符 delete 可以记录该事实以及有问题的指针的值,从而有助于在提供良好的诊断信息方面。

提高效率(速度和内存):
newdelete运算符(operator)对每个人都工作得相当好,但对任何人来说都是最佳的。这种行为源于这样一个事实,即它们仅被设计用于一般用途。它们必须适应分配模式,从在程序持续时间内存在的几个块的动态分配到大量短期对象的持续分配和解除分配。最终,运营商new和运算符(operator) delete带有编译器的产品采用中间策略。

如果您对程序的动态内存使用模式有很好的了解,您通常会发现自定义版本的 operator new 和 operator delete 优于默认版本(性能更快,或需要的内存减少高达 50%)。当然,除非您确定自己在做什么,否则这样做不是一个好主意(如果您不了解所涉及的复杂性,甚至不要尝试这样做)。

收集使用统计:

在考虑更换之前newdelete为了提高 #2 中提到的效率,您应该收集有关您的应用程序/程序如何使用动态分配的信息。您可能想要收集有关以下方面的信息:
分配块的分布,
生命周期分布,
分配顺序(先进先出或后进先出或随机),
了解使用模式在一段时间内的变化,使用的最大动态内存量等。

此外,有时您可能需要收集使用信息,例如:
统计一个类的动态对象的数量,
限制使用动态分配等创建的对象数量。

所有,这个信息可以通过替换自定义new来收集和 delete并在重载的new中添加诊断收集机制和 delete .

补偿 new 中的次优内存对齐:

许多计算机体系结构要求将特定类型的数据放置在内存中特定类型的地址中。例如,体系结构可能要求指针出现在四的倍数(即四字节对齐)的地址处,或者 double 必须出现在八的倍数(即八字节对齐)的地址处。不遵守此类约束可能会导致运行时出现硬件异常。其他架构更宽容,并且可能允许它在降低性能的情况下工作。运算符new某些编译器附带的不保证动态的八字节对齐
double 的分配。在这种情况下,替换默认运算符 new使用一个保证八字节对齐的方法可以大大提高程序性能,并且可以成为替换 new 的一个很好的理由。和 delete运营商。

将相关对象聚集在一起:

如果您知道特定的数据结构通常一起使用,并且您希望在处理数据时最小化页面错误的频率,那么为数据结构创建一个单独的堆是有意义的,以便它们聚集在一起页尽可能。 new 的自定义放置版本和 delete可以使实现这种聚类成为可能。

获得非常规行为:

有时您希望运算符 new 和 delete 执行编译器提供的版本不提供的操作。
例如:您可以编写自定义运算符 delete用零覆盖已释放的内存,以提高应用程序数据的安全性。

关于c++ - 为什么要替换默认的 new 和 delete 运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7149461/

相关文章:

c++ - 在模板类上重载运算符

c# - 如何在使用 LINQ C# 创建新对象时访问内部属性?

c++ - 类的条件执行

c++ - C++中的strchr如何保证其调用者不会修改作为参数传递的字符串

c++ - 矩阵求逆 GPU MATLAB

c# - C# 中有什么方法可以在派生类中强制执行运算符重载吗?

c++ operator new 这在内部是如何工作的

c# - 是否有用于在 Windows Server 2008 中创建自定义服务器角色的 API?

c++ - 如何最正确地使用 libusb 与连接的 USB 设备通信?

c++ - 为什么我不必在 C++ 中重载赋值运算符?