2011-12-20 53 views
8

我想知道我的代碼的哪個部分將釋放一個動態分配,但靜態類成員,當這不再需要。請參閱以下代碼:classPrinter在所有A對象中共享,並在創建類A的第一個實例時創建。只要確定:classPrinter -object在退出我的程序時會自動被破壞,對吧?C++靜態類成員,誰清理混亂?

A.H

class A { 
static B* classPrinter; 
} 

a.cpp

#include "a.h" 
B A::classPrinter = new B(); 

A::A() { ...} 
+3

智能指針是良好的這種事情,至少,如果你真的需要動態分配(見[SBI的答案](http://stackoverflow.com/a/8578256/10077)。 – 2011-12-20 16:01:32

+1

確認....靜指針==邪惡 – 2011-12-20 16:58:58

回答

19

只要確定:somePrinter -object在退出我的程序時會自動被破壞,對吧?

既然這是C++,答案是「否」。對於使用new分配的所有內容,必須調用相應的delete。如果沒有發生,該對象泄漏。但爲什麼動態分配呢?這

class A { 
    static B classPrinter; 
} 

B A::classPrinter; 

行爲就像你的代碼,但classPrinter將在節目結束時破壞。

但是,你寫的

classPrinter是所有A-對象共享和創建時A類的第一個實例將被創建。

您問題中的代碼不會這樣做。 如果要做到這一點,做這樣的事情:

class A { 
    static std::shared_ptr<B> classPrinter; 
} 

std::shared_ptr<B> A::classPrinter; 

A::A() 
{ 
    if(!classPrinter) 
    classPrinter.reset(new B()); 
} 

智能指針將確保該對象被刪除。

+1

「在所有A-對象和當創建類A的第一個實例時創建「 – pezcode 2011-12-20 16:03:03

+0

@pezcode:我想你指的是」在創建A類的第一個實例時創建的。「我讀了,但問題中的代碼也是一樣的作爲我的代碼(當然除外泄漏) – sbi 2011-12-20 16:06:38

+0

可能是新運算符超載,我認爲它不是這樣,但理論上它可能。 – Yola 2011-12-20 16:07:01

3

其中以不會被調用A::classPrinter點的對象的析構函數。

如果你認爲這不是別的,而是邏輯;匹配delete - 在正常情況下,會調用對象的dtor?

佔用的內存將被標記爲空閒並返回到系統,至少在所有現代這樣的情況下。

+0

@sbi我不確定是否有機會在評論前後評論我的帖子,但我確實改變了措辭,以便更容易理解。 – 2011-12-20 16:00:46

0

如果A::classPrinter在多個成員之間共享,也許使用std :: shared_ptr而不是原始指針?在所有對它的引用都沒有的時候它會被自動刪除。

但是,是的,內存將在程序退出後回收,至少在所有操作系統的我能想到的...

0

您需要創建一些包裝或者使用類似的shared_ptr保證析構函數調用。

10

不,不會自動刪除使用new創建的對象。您應始終提供匹配delete以防止內存泄漏。

在這種情況下,最簡單的解決方案是擁有一個靜態對象,而不是一個指向動態對象的靜態指針 - 完全沒有理由爲額外的間接級別。

// header file 
class A { 
    static B classPrinter; 
}; 

// source file 
B A::classPrinter; 

,或者如果你想直到需要的對象推遲建設(和避免潛在問題,如果在其他翻譯單位的靜態對象需要從它們的構造函數訪問):

class A { 
    static B & classPrinter() { 
     static B instance; 
     return instance; 
    } 
}; 

在其他在實際需要動態分配的情況下,應始終使用智能指針或其他對象來管理動態對象。

+1

本地靜態是一個很好的技巧,我忘了提及。 '+ 1'。 – sbi 2011-12-20 16:54:14

0

靜態(就靜態成員變量而言)固有的含義始終存在。

如果你製作了一個靜態指針,你根本無法在一個有意義的點釋放。你需要更多的上下文。

如果您希望僅在擁有靜態成員所有者類的實例時存在共享數據,則需要一個靜態計數器。無論何時創建實例和計數器== 0,都會分配一個新的靜態值。每當刪除所有者類的最後一個實例時,請取消分配當前靜態值。否則,你將不得不陷入像共享或智能指針那樣釋放的東西,但即使這樣你也會遇到問題。如果智能指針沒有看到更多的引用並釋放,它可能會太早。如果它處於釋放狀態,那麼當您再次需要這些信息時,這意味着什麼。你分配一個新的靜態值?

如果靜態成員需要始終存在,無論您是否擁有所有者類的實例,則應考慮將指針改爲參考或實例。