2013-07-23 104 views
1

OK ..所以這讓我困惑。我正在處理一些遺留的C++代碼部分,我有一種感覺是不安全的,但我不是100%確定的。這裏有一個片段,例如有風險的東西。關於刪除C++指針

struct A { 
    A() : a_ptr(0) {} 
    A(some_type *ptr) : a_ptr(ptr) {} 
    const some_type *a_ptr; 
}; 

struct B { 
    B() : b_ptr(0) {} 
    B(some_type *ptr) : b_ptr(ptr) {} 
    const some_type *b_ptr; 
}; 

struct Data { 
    Data(...) {//-Stuff that doesn't invole aptr_list or bptr_list; 
    } 
    ~Data() { 
     for(std::vector<A*>::iterator itr = aptr_list.begin(); itr != aptr_list.end() ++itr) { 
      delete *itr; 
     } 
     for(std::vector<B*>::iterator itr = bptr_list.begin(); itr != bptr_list.end() ++itr) { 
      delete *itr; 
     } 
    } 
    std::vector<A*> aptr_list; 
    std::vector<B*> bptr_list; 
private: 
    Data(const Data&); 
    Data& operator=(const Data&); 
}; 

然後在實現中,我發現:

void some_func(...) { 
    //-Inside some function 
    Data& d = get_data(...); 
    ... 
    for(...) { 
     some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer); 
     A* a = new A(sptr); 
     B* b = new B(sptr); 
     d.aptr_list.push_back(a); 
     d.bptr_list.push_back(b); 
    } 
} 

我有點不安相同的指針在上面的實施正在使用sptr;當調用Data的析構函數時會造成問題嗎?另一方面,它看起來像我們有兩個new呼叫A*B*和正好兩個delete s,所以如果Data中的析構函數不深 - 也許這就是我需要澄清的地方,那麼也許這是安全的,畢竟我的關注是錯位的?我注意到,例如AB的結構沒有定義任何析構函數,所以我希望它不深。但我不確定這是否意味着它們的指針數據將被釋放。一如既往地欣賞專家的見解。

謝謝你的時間和興趣。

回答

2

AB沒有一個用戶定義的析構函數,所以裏面什麼也沒有ab被破壞(比它擁有被釋放出來的實際內存等,但由於sptr只是在那裏舉行,它是不是被deleted)。 [很明顯,如果AB包含其他類別,例如std::stringstd::vector,該類別將被銷燬]。

因此,換句話說,你的代碼是蠻好喜歡它 - ab僅持有的sptr副本,但它永遠不會被刪除[在此位的代碼,如果它需要以後刪除,那是另一回事]。

+0

謝謝,這令人放心。 :-) –

1

sptr不屬於A或B,所以這是正確的。

+0

只要'* sptr'的生命週期包含使用它的'B'和'B'對象的生命週期。 –

+0

的確,但問題是關於調用Data ::〜Data。 – MSalters

+0

謝謝@MSalters:但是什麼是正確的呢? –

2

Data::~Data()不會破壞sptr指針。它只會撥打A::~A()B::~B()

我不確定你想要做什麼,但是如果你想要一個很深的破壞,你需要確保你沒有釋放一個以前已經被某人釋放的內存地址。

這取決於實施要求,但理想情況下分配對象的用戶也應該可以自由使用。因此,由於此sptr分配給其他人,如果您釋放它,您可能會得到一個懸掛指針。

1

如果我們真的有些綽綽有餘,那麼代碼可能會泄漏

如果d.aptr_list.push_back()需要並且未能預留更多容量,則ab指向的內存將會泄漏。

for(...) { 
    some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer); 
    A* a = new A(sptr);   // Allocate memory 
    B* b = new B(sptr)   // Allocate memory (and missing semicolon!!) 
    d.aptr_list.push_back(a); // If this fails, 
    d.bptr_list.push_back(b); // or this, 
}         // then exception is thrown and memory is lost 
            // (unless you catch the exception and 
            // perform a delete). 

您應該使用智能指針像std::unique_ptr環繞指針的安全。

你的名單應該是std::vector<std::unique_ptr<A>>類型和std::vector<std::unique_ptr<B>>的。

some_func代碼可以讀取這樣的事情:

some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer); 
d.aptr_list.push_back(std::unique_ptr<A>(new A(sptr))); 
d.bptr_list.push_back(std::unique_ptr<B>(new B(sptr)));