2014-09-20 106 views
0

对象在C++中,你可以解除分配分配给对象这样的记忆:(或任何其他情况下)释放内存分配给Java中

int main(){ 
    string myString("MyString"); 
    string *stringPointer = &myString; 
    cout<<myString<<" "<<*stringPointer; 
    delete stringPointer; 
    cout<<myString; //crash 
    return 0; 
} 

在二叉搜索树,当你需要删除一个节点,你使它有资格在Java中进行垃圾收集。但你不能做这样的

Node nodeToDelete = getNodeToDelete(); 
nodeToDelete = null; //the original reference is still there in the tree 

这就像设置一个指针变量设置为NULL在C++

pointerVariable = NULL; 

对于BST删除功能在Java中的工作,我们需要去父并将该子节点设置为空删除。 在C++中是否存在类似于删除的Java语言功能以使事情更简单?

+0

你不需要'delete',java提供垃圾回收功能。 – 2014-09-20 09:33:55

+0

如果您有一种搜索树中可删除节点的方法,为什么不将该节点设置为null? – Tom 2014-09-20 09:36:31

+0

我的意思是说有没有办法让一个对象符合垃圾回收的条件,但它仍然有引用? (如在C++中删除) – CodeWriter 2014-09-20 09:37:01

回答

1

不,Java中没有语言功能,允许您提前有选择地删除特定对象(如Python中的del)。你需要相信垃圾收集器将会完成它的工作。 (通常,它的确如此。)

Java的垃圾回收器基于对象可达性(不像CPethon中的引用计数,而不像Boehm GC中的内存扫描)。这使得任何没有实时引用的对象都会被垃圾收集。该参考可以是间接的,但是从死物和死循环的参考不会刺激车库收集器。

一些例子:

class Dummy { 
    String name; 
    Dummy other; 
    Dummy(String name) { this.name = name; } 
} 

void f1() { 
    Dummy peter = new Dummy("Peter"); 
    peter.other = new Dummy("Fred"); 
    peter.other.other = new Dummy("Megan"); 
    // None of the objects is eligible for garbage collection since 
    // "Peter" is live and "Fred" can be reached via "Peter" (therefore 
    // "Fred" is alive) and "Megan" can be reached via "Fred". 
    peter.other = null; 
    // Now the reference to "Fred" is lost which makes him a candidate 
    // for garbage collection. "Megan" is dead too because the 
    // reference from the dead object "Fred" does not count. 
    // As the method returns, all three objects are dead and can be 
    // collected. 
} 

void f2() { 
    Dummy clementine = new Dummy("Clementine"); 
    clementine.other = new Dummy("Charles"); 
    clementine.other.other = new Dummy("Caroline"); 
    clementine.other.other.other = clementine; 
    // Here we have a cycle of 
    // 
    // +--> "Clementine" --> "Charles" --> "Caroline" --+ 
    // |            | 
    // +------------------------------------------------+ 
    // 
    // and since "Clementine" is live, all three are. 
    clementine = null; 
    // Once we loose the reference to "Clementine", the cycle still 
    // exists (every object is referenced by at least one other object) 
    // but the cycle is dead. Hence, all three are subject to garbage 
    // collection. 
} 

的关键在于使用Java的垃圾回收实际上是不保留任何引用到周围的物体,你不需要任何更多。在你的二叉树中,做

this.leftChild = null; 

会使整个左边的子树符合垃圾回收的条件。 (也就是说,如果没有其他人保留对其中一个节点的实时参考)。

只有很少您会希望允许垃圾回收器收集活动对象。这可以使用java.lang.ref.SoftReference来完成。我发现它们有用的唯一时间就是缓存。

import java.lang.ref.SoftReference; 

class StoryOfMyLife { 
    private final String story; 
    private transient SoftReference<String[]> cachedWords; 

    public StoryOfMyLife(final String story) { 
     this.story = story; 
     this.cachedWords = new SoftReference<String[]>(null); 
    } 

    public synchronized String getWordN(final int n) { 
     String[] words = this.cachedWords.get(); 
     if (words == null) { 
      // Called for the first time or cache was garbage collected. 
      words = this.story.split("\\s+"); 
      this.cachedWords = new SoftReference<String[]>(words); 
     } 
     // Note that we are keeping the cache live for the duration of 
     // this method by keeping the reference 'words'. Once this 
     // method returns, the cache becomes subject to garbage 
     // collection again. 
     return words[n]; 
    } 
} 

在这个例子中,将长字符串拆分成单词的操作(可能非常昂贵)只是懒懒的完成,结果被缓存。但是,如果系统内存不足,我们允许缓存被垃圾收集,因为我们可以随时重新计算它。

您可以在Oracle's website上阅读有关内置于Oracle HotSpot JVM中的垃圾回收器的更多信息。

0

Java通过基于可达性的垃圾收集来管理内存,因此为了释放内存,只需确保它不再可及。

很少的Java对象需要及时清理:

即那些管理本机资源。使用dispose()if block-scoped, try using

侧面说明:C++是为了释放内存与错误的方法过敏:

  • 使用范围退出自动存储​​(也就是你用什么)。这是RAII的基础。
  • 使用delete补充new。使用delete []补充new[]
  • 使用free来补充malloc,callocrealloc