2014-09-20 111 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