【问题标题】:Why do you need to allocate memory in c/c++?为什么需要在 c/c++ 中分配内存?
【发布时间】:2019-04-20 02:03:35
【问题描述】:

切入正题:在 c++ 中需要分配内存的原因是什么?

我了解某些编程语言会自动执行此操作,但在 C/C++ 中:必须分配内存的原因是什么。例如: 在声明 PROCESSENTRY32 时,为什么我们需要 ZeroMemory() 呢?在为套接字程序制作缓冲区时,为什么我们需要 ZeroMemory() 呢?为什么声明 int 数据类型时不需要分配内存?

【问题讨论】:

  • 分配的内存超过了它被分配的范围。
  • 4) “动态”分配内存的主要原因是您可以控制对象的生命周期。如果您让语言来执行此操作,则对象的生命周期是预先定义的(并且定义非常严格),但是通过使用“动态”分配,您可以显式控制其生命周期何时结束以及何时被销毁(因此对于调用析构函数时的对象)。
  • Python 和 Java 在为您处理内存时所做的事情称为“垃圾收集”(略读:“en.wikipedia.org/wiki/Garbage_collection_(computer_science)”)。在我看来,我认为 C++ 被设计为尽可能快的运行时,这指导了许多设计选择。我怀疑 Stroustrup(C++ 的创建者)不想花费计算能力来跟踪内存,当您想到 1970 年代末/1980 年代初 CPU 有多快(慢?)时,这是可以理解的。
  • 我已经编写了大量没有malloc 的嵌入式/裸机固件。动态分配超出了它的范围。因此,您可以将内存返回给调用者,他可以随心所欲地使用内存。在没有内存分配的情况下,调用者需要提前知道用户将输入多少字符到您的程序中。试着告诉用户。比如“输入超过 8 个字符软件会崩溃”。首先认为他们这样做 - 输入 9 看看会发生什么。 Python和Java使用方式,方式更多动态分配只有一个被解释,另一个有垃圾收集器
  • @JohnPhode:请不要在 C++ 程序中使用malloc()。这只是另一种语言(C)的保留。 C++ 具有与 C 完全不同的内存处理技术。此外,在现代 C++ 中,我们使用辅助对象(智能指针)内联执行细粒度确定性垃圾收集,而不是依赖于 Java 和 Python 等语言使用的单独的整体垃圾收集系统。

标签: c++ c memory memory-management


【解决方案1】:

你的问题真的没有意义。 ZeroMemory 不分配内存;它只是将字节设置为0。如果需要,您可以轻松地 ZeroMemoryint。只是i = 0;写的比较短。

在所有情况下ZeroMemory 仅适用于已经存在的内存;即之前必须有其他东西分配过它。

至于实际分配,C区分对象的三种存储方式:

  1. 静态存储。这些对象在程序启动时分配,并在程序运行时一直存在。示例:全局变量。

  2. 自动存储。这些对象在执行到达其范围时分配,并在执行离开其包含范围时释放。示例:局部变量。

  3. 动态存储。这是您通过调用 malloc / calloc / realloc / free 手动管理的。

您真正必须自己分配内存的唯一情况是情况 #3。如果您的程序仅使用自动存储,则无需做任何特殊操作。

在像 Java 这样的语言中,您仍然必须通过调用 new 来分配内存。 Python 没有new,但是例如每当您执行[...]{...} 之类的操作时,它都会创建一个新的列表/字典,用于分配内存。 关键部分实际上是您不必释放内存。

Java 或 Python 等语言包含垃圾收集器:您创建对象,但该语言负责清理您身后的内容。当不再需要一个对象时1,它会被自动释放。

C 不会那样做。原因在于它的历史:C 是作为汇编代码的替代品而发明的,目的是使将 Unix 移植到新计算机上更容易。自动垃圾收集需要一个运行时系统,这会增加复杂性并可能存在性能问题(即使是现代垃圾收集器有时也会暂停整个程序以回收内存,这是不可取的,C 语言早在 1972 年就已创建)。

没有垃圾收集器会导致 C

  • 更容易实施
  • 更容易预测
  • 可能更高效
  • 能够在非常有限的硬件上运行

C++ 旨在成为“更好的 C”,针对相同类型的受众。这就是为什么 C++ 几乎保留了 C 的所有特性,即使是那些对自动垃圾回收非常不友好的特性。


1 不完全正确。内存在不再可访问时被回收。如果程序仍能以某种方式到达某个对象,即使它不再真正需要它也会保持活动状态(另请参阅:Space leak)。

【讨论】:

    【解决方案2】:

    C 选择是相对低级的语言,其中语言构造或多或少直接映射到最多几条机器指令。

    块级分配,例如 in

    int main()
    {
       int a,b,c; //a very cheap allocation on the stack
       //... do something with a, b, and c
    }
    

    属于这一类,因为函数中的所有块级分配通常会转换为对堆栈指针的一次减法。

    这些分配的缺点是它们非常有限——你不应该像这样分配大对象或多个对象(否则你会冒堆栈溢出的风险)而且它们也不是很持久——它们很有效在范围末尾撤消。

    至于来自主内存的通用分配,除了一大堆 char(即您的 RAM)和可能的一些虚拟内存映射工具(即,将真实内存映射到更小的内存)之外,机器并没有真正为您提供太多字符数组)。有多种方法可以分割这些数组以及使用和重用这些片段,因此 C 将其留给库。 C++ 在 C 之后。

    【讨论】:

      猜你喜欢
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      • 2021-09-05
      • 2014-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多