首页 > 解决方案 > 类应该自己管理动态内存吗?

问题描述

如果一个类需要动态分配内存(例如std::vector),该类是否可以在内部使用运算符new或? 简单地分配和释放内存malloc

答案对我来说并不完全清楚。缺乏像垃圾收集语言那样管理内存分配的系统显然是有能力的。但另一方面,正是这种缺乏协调最终导致了记忆的浪费。例如,制作一个“假”分配器将堆栈内存传递给在正常情况下需要动态内存但程序员可以断言永远不需要超过 X 字节数量的对象是非常简单的。

也许你认为这个问题在大地址空间的时代已经无关紧要了,但是回到硬件上感觉有点蹩脚,毕竟这是 C++。

编辑

我现在意识到我对这个问题有多么神秘......让我解释一下。

当我说“浪费内存”时,我特别指的是堆碎片造成的那种内存浪费。减少堆碎片是在 C++ 中创建内存管理系统最引人注目的一点,因为(正如许多评论所指出的)析构函数已经处理了资源管理方面的事情。当您的分配基本上是随机的(您不知道新内存相对于其他已分配内存的位置)并且每个类都可能分配时,您会遇到面向数据的设计试图解决的问题:数据局部性差。

所以问题是:有一个类来执行内存管理、对象管理、堆压缩,也许还有统计跟踪(用于调试目的)以最有效地利用内存和数据局部性是否有意义?

[在这种观点下,每个动态分配内存的类或函数都必须以某种方式获得对该类的引用。]

还是让每个类都能够分配而不一定使其成为该类接口的一部分更好?

标签: c++memory-management

解决方案


如果一个类需要动态分配内存(例如std::vector),该类是否可以在内部使用运算符new或? 简单地分配和释放内存malloc

通常,我们有两种类:

  • 资源管理器(包括动态内存);
  • “业务逻辑”类。

大多数时候我们不应该混合资源管理和域逻辑层

因此,如果您的类是原始资源的管理器,它会分配/取消分配、初始化/取消初始化其唯一资源,并且不执行任何其他操作。在这种情况下,new是可以的,甚至是必要的(例如,您不能std::vector在编写自己的动态数组时使用它,否则您根本不需要编写它)。请参阅RAII

如果您的类包含一些应用程序逻辑,则不允许显式分配动态内存、打开套接字等,但它使用其他 RAII 类。在这个高级 C++ 为您提供了 GC 语言所没有的东西:它使 RAII 所有者管理文件、套接字等 - 任何类型的资源,而不仅仅是堆内存的原始字节,因此您不需要手动 Java/ C# 风格的 try-with-resources 在您创建非原始内存管理器对象的任何地方 - 只要您有一个 RAII 类,编译器就会为您执行此操作。


推荐阅读