【问题标题】:what happens to unused memory in C++C ++中未使用的内存会发生什么
【发布时间】:2011-06-18 11:29:23
【问题描述】:

我正在经历一些练习编码问题,我遇到了一个 -

实现一个算法来删除单个链表中间的一个节点, 仅授予对该节点的访问权限。

示例:
输入:链表中的节点“c”a->b->c->d->e
结果:什么都没有返回,但是新的链表看起来像a->b->d->e

解决这个问题的方法是简单地将数据从下一个节点复制到这个节点,然后 删除下一个节点。

上述解决方案将 java 作为编程语言牢记在心。 我想知道已删除节点的内容会发生什么?它的命运在 java 和 c++ 中会有所不同吗? 而且,我认为这个问题的完美答案还应该释放已删除节点的内存。我们如何在 C++ 中做到这一点?

【问题讨论】:

  • 对于 C++,每个人要么说“使用delete”,要么在一种情况下说“使用deletefree”。为了释放内存你必须知道它是如何分配的,所以要完成这个问题,它几乎必须告诉你如何释放内存。由于它在问题中未知,我认为一个完美的答案应该提到我们不知道如何释放节点,或者应该提供完整的列表定义和实现,包括分配。如果该问题是一系列问题中的一个,那么您可能已经在之前的问题中完成了后者。
  • @Steve Jessop - 请详细说明“如何分配”是什么意思?你的意思是在堆栈上还是在堆上?
  • 我的意思是使用newmalloc 或一些自定义分配器。在自定义分配器的情况下,它分配的内存池可能恰好在堆栈上,但这并不是重点。或者您可以创建一个自动(“在堆栈上”)列表节点数组,然后将它们链接到一个列表中,然后从列表中删除其中一个。在这种情况下,您什么都不做,当它们超出范围时,它将与其他人一起释放。在 C++ 中有很多方法可以获取内存,因此也有很多方法可以释放它。
  • 我认为史蒂夫所说的是列表管理应该与内存管理分离。如果节点的类编写正确,则节点的用户不必同时执行这两项操作。作为列表的用户,您只需从列表中删除节点。节点类应该以这样一种方式编写,即它们会自动被删除(就像在 Java 中一样)。查找Seporation of Concenrnsmart pointer

标签: java c++ garbage-collection memory-management linked-list


【解决方案1】:

还应该释放已删除节点的内存。

是的。

我们如何在 C++ 中做到这一点?

使用delete 运算符。

如果您正在处理链接列表并且不了解delete 运算符,您可能会走题。你不想在学习 C 或 C++ 时跳过步骤;以后它会咬你的头。

【讨论】:

    【解决方案2】:

    在 Java 中,内存最终会被垃圾收集器释放。无法保证何时(以及是否)会发生这种情况。 (实际上,它通常会很快发生)。

    在带有智能指针的 C++ 中,一旦对象无法再被寻址,就会保证内存的释放。实际上,只要您没有任何循环引用图,它的工作原理就与 Java 中的垃圾收集非常相似。

    如果您不使用智能指针,则必须手动调用delete c(或free(c))。如果你不这样做,你的程序将分配内存,它永远不会再次使用。

    【讨论】:

    • 在 C++ 代码中看到删除通常是设计草率的结果。我几乎从没想过会在用户代码中看到它。设计应该使用智能指针,因此不需要删除它隐含的对象。这是基本的关注点分离原则,其中列表的管理与内存资源的管理是分开的,并且在执行一项任务时,用户不应接触到另一项任务。
    • @Martin 已更新。我错过了什么吗?
    【解决方案3】:

    嗯,这并不完全是您在 C++ 中所做的。你应该做什么/会发生什么:

    1. 删除c指向的内存。
    2. 将指向内存的指针从d复制到c
    3. 将指向e 的指针从d 复制到c

    现在我们有效地将d 从列表中删除,并使c 的行为与d 一样。最后,如果d 本身也被分配到某个地方并且必须单独删除,则在 3 之后将其删除。

    为什么是 1?因为在 Java 中,如果一个对象不再使用,它​​会自动被垃圾回收。在 C++ 中,情况并非如此。

    【讨论】:

    • 我觉得你应该先复制东西,最后再删除内存。
    • Paŭlo Ebermann:不。在出现问题或抛出异常的情况下,我们使内存不可访问,但我们没有释放它。
    • 嗯,现在你正在访问释放的内存,这样更好吗?
    • 好 :) 无论如何,出现问题的可能性极低,在释放完成后,如果您首先复制指针,那么您需要一个临时的旧指针仍然需要释放。反正没有太大区别。
    【解决方案4】:

    为了回答问题标题“C++ 中未使用的内存会发生什么”,内存管理器将内存标记为未分配,但为了提高效率,可能不会在此时(如果有的话)返回给操作系统。释放是通过 delete 关键字

    进行的

    对于您的具体示例(匆忙拼凑在一起):

    假设一个节点如

    struct Node
    {
        Node* next;
    } head;   
    
    //Later...
    
    Node* pred = head; //Where head is the start of the list
    while((pred->next != NULL) && (pred->next != c))
    {
       pred  = pred->next;          
    }
    
    Node* toDelete = pred->next;
    Node* newSuccessor = toDelete->next;
    
    /*
      This is the moment when the memory is considered freed. 
      free() should only be used if the node was allocated with malloc()
    */
    delete toDelete; 
    
    pred->next = newSuccessor; 
    

    【讨论】:

    • C++ 类应该很少包含 RAW 指针。使用智能指针。因此,我不希望在代码中看到删除。
    • 我完全同意,这将是一个很好的替代答案。如果只有人们的期望支配了实际在野外发现的代码。
    【解决方案5】:

    在 Java 中,它最终会被作为垃圾收集。在 C++ 中,您必须使用 delete 关键字显式释放它。

    一旦内存被释放,实际位将保持不变,但可能随时重新分配和覆盖。

    【讨论】:

      猜你喜欢
      • 2018-04-08
      • 2022-01-13
      • 2021-07-08
      • 1970-01-01
      • 2013-09-06
      • 2014-11-15
      • 2018-06-08
      • 1970-01-01
      • 2011-12-25
      相关资源
      最近更新 更多